perm filename SUPDUP.MID[NET,MRC]6 blob sn#336683 filedate 1978-02-20 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00064 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00006 00002	Assembly options, etc.
C00009 00003	AC's, I/O channels, macros
C00011 00004	SUPDUP documentation
C00016 00005	BACKGROUND
C00021 00006	INITIALIZATION
C00027 00007	INITIALIZATION (continued)
C00029 00008	TTYOPT FUNCTION BITS
C00033 00009	TTYOPT FUNCTION BITS (continued)
C00036 00010	INPUT -- THE INTELLIGENT TERMINAL PROTOCOL
C00041 00011	INPUT -- THE INTELLIGENT TERMINAL PROTOCOL (continued)
C00045 00012	OUTPUT -- DISPLAY PROTOCOL (%TD CODES)
C00049 00013	OUTPUT -- DISPLAY PROTOCOL (%TD CODES) (continued)
C00052 00014	OUTPUT -- DISPLAY PROTOCOL (%TD CODES) (continued)
C00054 00015	STANFORD/ITS CHARACTER SET
C00057 00016	STANFORD/ITS CHARACTER SET (continued)
C00060 00017	ACKNOWLEDGEMENTS
C00062 00018	SUPDUP.MRC[UP,DOC]
C00066 00019	 SUPDUP FEATURES:
C00070 00020	 Everything nobody wanted to know about SUPDUP's internal mappings
C00073 00021	ITS TTY definitions
C00077 00022	ITS output buffer codes
C00079 00023	SAIL system definitions
C00083 00024	Data area
C00086 00025	 IMP MTAPE command words
C00088 00026	Display crufties
C00091 00027	 More display data stuff
C00094 00028	UUO server
C00097 00029	Interrupt server
C00100 00030	Startup, etc.
C00102 00031	 Initial terminal setup
C00106 00032	Monitor command processor
C00108 00033	Get host name
C00111 00034	ICP ICP ICP
C00114 00035	 Get socket number from logger
C00118 00036	Final pre-display initialization
C00120 00037	Slurp up and send terminal ID
C00123 00038	 Now search for terminal
C00126 00039	Initialize screen
C00128 00040	TTY input service
C00130 00041	 Output a character to the network buffer in the hairy way
C00135 00042	Network input service
C00138 00043	 Check for other display stuff
C00140 00044	 Subroutines for network input service
C00143 00045	Display hacking
C00146 00046	Display subroutines
C00150 00047	 Non-insert/delete display subroutines
C00154 00048	 More display subroutines
C00157 00049	 Line insert
C00159 00050	 Line delete
C00161 00051	 Character insert
C00164 00052	 Character delete
C00167 00053	Display update subroutines
C00171 00054	 More display updating stuff
C00173 00055	DM display routines
C00178 00056	SUPDUP commands
C00180 00057	 Display only commands
C00183 00058	 Esoteric character mappings (all magical)
C00186 00059	 Magic DDT command, subroutines, etc.
C00187 00060	 SUPDUP help text
C00188 00061	Screen record crock
C00191 00062	Network error analysis
C00193 00063	 More network error reporting
C00196 00064	Random routines, literals, etc.
C00198 ENDMK
C⊗;
subttl Assembly options, etc.

title SUPDUP

; Mark Crispin, SU-AI, February 1978

;  This is the SAIL implementation of the ITS SUPDUP program, which is used
; for display communication across ITS systems.  The protocol is described
; in RFC 734, NIC 41953.

.nstgw					; no storage words allowed

if2,[	; Second time through just print switch settings
 swprint \pdllen,words of PDL storage.
 swprint \<pgmbeg-corbeg>,words impure storage.
 swprint \<sdpff-pgmbeg>,words pure storage.
 swprint \dmbufl,words DM buffer storage.
 swprint \icpskt,is the ICP socket.

 radix 10.				; print these in decimal

 swprint \nlines,maximum lines in screen matrix.
 swprint \linel,maximum characters in screen matrix.
 swprint \nlnglt,line(s) per glitch when scrolling.
 swprint \nlnupd,minimum lines changed to cause full screen update.
 swprint \clkspd,seconds between clock interrupts

 radix 8.				; back to octal

.hkill icp,net,dsk			; so DDT doesn't confuse these
					; with AC's on typeout
];if2

if1,[	; First time through define all macros, symbols, etc.

; Canonical macro library

.insrt MACROS[1,MRC]

; Assembly switches

nd. icpskt==137				; new SUPDUP ICP socket
nd. pdllen==50				; length of pushdown stack
nd. dmbufl==200				; words of DM buffer space
nd. nlines==40.				; maximum number of lines on screen
nd. linel==88.				; maximum number of characters
nd. nlnglt==1				; number of lines to glitch when scrolling
nd. clkspd==3.				; three seconds of clock time
nd. nlnupd==3.				; number of lines that cause screen update
					; instead of updating individual lines

nchars==<<<linel+5>/5>*5>		; # chars/line; must be a multiple of 5
subttl AC's, I/O channels, macros

; Accumulators

;  Things depend on the order of X, Y, Z, and A being consecutive.  U and T
; are used at UUO level.
 
acdef. [x y z a b c t u]

; I/O channels

;  ICP is used for ICP'ing only, NET is the general network work channel,
; DSK is used for reading ROOMS[P,DOC] and for recording the screen.

acdef. [icp net dsk]

; Macros

; Print out switch settings

define swprint value,line/
 printx/value line
/
termin

; Map character in ac to char2 if it contains char1 now

define mapit ac,char1,char2
 caxn ac,char1
  jrst [movx ac,char2
	return]
termin

; Generate a Data Disc command

define ddcmd o1,d1,o2,d2,o3,d3
 .byte 8.,8.,8.,3.,3.,3.,3.
  d1 ? d2 ? d3 ? o1 ? o2 ? o3 ? 4
 .byte
termin

; Send a DM command character

define dmcmd ch
 move x,dmcnt
 caxge x,10
  call dmout
 movx x,177
 call dmchar
 movx x,ch
 call dmchar
termin
subttl SUPDUP documentation

COMMENT ⊗

NWG/RFC# 734				        MRC 07-OCT-77 08:46  41953
SUPDUP Display Protocol

Network Working Group					      Mark Crispin
Request for Comments 734					     SU-AI
NIC 41953						    7 October 1977

			  SUPDUP Protocol

INTRODUCTION

This document describes  the SUPDUP protocol,  a highly efficient  display
telnet protocol.  It originally started as a private protocol between  the
ITS systems at MIT to allow a user at any one of these systems to use  one
of the others as a display.  At the current writing, SUPDUP user  programs
also exist  for  Data  Disc  and  Datamedia  displays  at  SU-AI  and  for
Datamedias at SRI-KL.  The author is not aware of any SUPDUP servers other
than at the four MIT ITS sites.

The advantage  of  the  SUPDUP  protocol  over  an  individual  terminal's
protocol is that SUPDUP defines a "virtual" or "software" display terminal
that implements relevant  cursor motion operations.   The protocol is  not
built on  any  particular  display  terminal but  rather  on  the  set  of
functions common to all display terminals; hence it is completely  device-
independent.  In addition, the protocol also provides for terminals  which
cannot handle certain operations, such as line or character insert/delete.
In fact,  it is  more than  this.   It provides  for terminals  which  are
missing any set of features, all the way down to model 33 Teletypes.

The advantage over the TELNET protocol  is that SUPDUP takes advantage  of
the full  capabilities of  display  terminals, although  it also  has  the
ability to run printing terminals.

It is to be  noted that SUPDUP operates  independently from TELNET; it  is
not an option to  the TELNET protocol.   In addition, certain  assumptions
are made about the  server and the user  programs and their  capabilities.
Specifically, it is  assumed that the  operating system on  a server  host
provides all the display-oriented features of ITS.  However, a server  may
elect not to do certain display operations available in SUPDUP; the SUPDUP
protocol is far-reaching enough so  that the protocol allows terminals  to
be handled  as well  as that  host can  handle terminals  in general.   Of
course, if a host does not  support display terminals in any special  way,
there is no point in bothering  to implement a SUPDUP server since  TELNET
will work just as well.

A more complete description  of the display facilities  of SUPDUP and  ITS
can be found by FTP'ing the  online file .INFO.;ITS TTY from ARPAnet  host
MIT-AI (host 206 octal, 134. decimal).  For more information, the  mailing
address for SUPDUP is "(BUG SUPDUP) at MIT-AI".  If your mail system won't
allow you to use parentheses, use Bug-SUPDUP@MIT-AI.
BACKGROUND

The SUPDUP protocol originated as the internal protocol used between parts
of ITS, and between ITS and "intelligent" terminals.  Over the network,  a
user host acts like an intelligent terminal programmed for ITS.

The way terminal  output works  in ITS is  as follows:   The user  program
tells the system to  do various operations,  such as printing  characters,
clearing the screen, moving the cursor, etc.  These operations are  formed
into 8-bit characters  (using the  %TD codes described  below) and  stored
into a  buffer.   At interrupt  level,  as the  terminal  demands  output,
characters are  removed  from  the buffer  and  translated  into  terminal
dependent codes.  At this time  padding and cursor motion optimization are
also done.

In some cases, the interrupt side does not run on the same machine as  the
user program.  SUPDUP terminals have their "interrupt side" running in the
user host.  When  SUPDUP is  run between two  ITS's, the  SUPDUP user  and
server programs and the network simply move characters from the buffer  in
the server machine to the buffer in the user machine.  The interrupt  side
then runs on the user machine just as if the characters had been generated
locally.

Due to the highly interactive characteristics of both the SUPDUP  protocol
and the ITS system, all transactions are strictly character at a time  and
all echoing  is  remote.  In  addition,  all padding  and  cursor  control
optimization must be done by the user.

Because this is also the internals of ITS, the right to change it any time
if necessary to provide new features  is reserved by MIT.  In  particular,
the initial  negotiation  is probably  going  to be  changed  to  transmit
additional variables, and additional %TD codes  may be added at any  time.
User programs should ignore those they don't know about.

The following conventions are  used in this  document: function keys  (ie,
keys which represent a "function"  rather than a "graphic character")  are
in upper case in square brackets.  Prefix keys (ie, keys which generate no
character but  rather are  held  down while  typing another  character  to
modify that  character)  are  in  upper case  in  angle  brackets.   Hence
"<CONTROL><META>[LINE FEED]" refers to  the character generated when  both
the CONTROL and META keys  are held down while a LINE FEED is typed.  Case
should  be  noted;  <CONTROL>A  refers  to  a  different  character   from
<CONTROL>a.  Finally, all numbers which  do not explicitly specify a  base
(ie, octal  or decimal)  should be  read  as octal  unless the  number  is
immediately followed by a period, in which case it is decimal.
INITIALIZATION

The SUPDUP server listens on socket 137 octal.  ICP proceeds in the normal
way for establishing 8-bit connections.   After the ICP is completed,  the
user side  sends several  parameters to  the server  side in  the form  of
36.-bit words.  Each  word is  sent through  the 8-bit  connection as  six
6-bit bytes, most-significant first.  Each byte is in the low-order 6 bits
of a character.  The first word is the negative of the number of variables
to follow in the high order 18. bits (the low-order 18. bits are ignored),
followed by the  values of  the TCTYP,  TTYOPT, TCMXV,  TCMXH, and  TTYROL
terminal descriptor variables (these  are the names they  are known by  at
ITS sites).  These  variables are  36.-bit binary numbers  and define  the
terminal characteristics for the virtual terminal at the REMOTE host.

The count is for future compatability.  If more variables need to be  sent
in the future, the server should assume "reasonable" default values if the
user does not specify them.  PDP-10 fans will recognize the format of  the
count (ie, -count,,0) as being an  AOBJN pointer.  At the present  writing
there are five variables hence this word should be -5,,0.

The TCTYP variable defines the terminal type.  It MUST be 7 (%TNSFW).  Any
other value is a violation of protocol.

The TTYOPT  variable specifies  what capabilities  or options  the  user's
terminal has.  A bit being true implies that the terminal has this option.
This variable also includes user options which the user may wish to  alter
at his or her own descretion; these options are included since they may be
specified along with the terminal capabilities in the initial negotiation.
See below for the relevant TTYOPT bits.

The TCMXV variable specifies the screen height in number of lines.

The TCMXH variable specifies the line width in number of characters.  This
value is one less  than the screen width  (ITS indicates line overflow  by
outputting an exclamation  point at  the end  of the  display line  before
moving to the  next line).  Note:  the terminal must  not do an  automatic
CRLF when a  character is  printed in the  rightmost column.   If this  is
unavoidable, the user SUPDUP must decrement the width it sends by one.

Note: Setting either the TCMXV or  TCMXH dimension greater than 128.  will
work, but will have some problems as coordinates are sometimes represented
in only  7 bits.   The main  problems occur  in the  SUPDUP protocol  when
sending the cursor position after an output reset and in ITS user programs
using the display position codes ↑PH and ↑PV.

The TTYROL variable specifies the "glitch count" when scrolling.  This  is
the number of lines to scroll up when scrolling is required.  If zero, the
terminal is not  capable of  scrolling.  1 is  the usual  value, but  some
terminals glitch up by more than one line when they scroll.

Following the transmission of the terminal options by the user, the server
should respond with an  ASCII greeting message,  terminated with a  %TDNOP
code (%TD codes are described  below).  All transmissions from the  server
after the  %TDNOP  are  either printing  characters  or  virtual  terminal
display codes.
INITIALIZATION (continued)

The user  and  the  server  now both  communicate  using  the  intelligent
terminal protocol (described below) from the  user and %TD codes from  the
server.  The user has two commands in addition to these; they are  escaped
by sending 300  (octal).  If following  the escape is  a 301 (octal),  the
server should attempt to  log off the remote  job (generally this is  sent
immediately before the user disconnects,  so this logout procedure  should
be done regardless of the continuing integrity of the connection).  If the
character following  the escape  is a  302 (octal),  all ASCII  characters
following up to a null (000  octal) are interpreted as "console  location"
which the server  can handle as  it pleases.  No  carriage return or  line
feed should be in the console location text.  Normally this is saved  away
to be displayed by the "who" command when other users ask where this  user
is located.
TTYOPT FUNCTION BITS

The relevant TTYOPT bits for SUPDUP usage follow.  The values are given in
octal, with the left and right 18-bit  halves separated by ",," as in  the
usual PDP-10 convention.

Bit name	Value		Meaning

%TOALT		200000,,0	characters  175  and 176  are converted to
				altmode (033) on input.

%TOERS		 40000,,0	this  terminal  is capable  of selectively
				erasing its  screen.  That is, it supports
				the %TDEOL,  the %TDDLF,  and (optionally)
				the  %TDEOF  operations.   For   terminals
				which   can   only   do   single-character
				erasing, see %TOOVR.

%TOMVB		 10000,,0	this  terminal  is capable of  backspacing
				(ie, moving the cursor backwards).

%TOSAI		  4000,,0	this   terminal   has   the   Stanford/ITS
				extended ASCII graphics character set.

%TOOVR		  1000,,0	this terminal is  capable of overprinting;
				if  two  characters  are  displayed in the
				same  position, they will both be visible,
				rather than one replacing the other.

				Lack of this capability but the capability
				to backspace (see %TOMVB) implies that the
				terminal can  do single  character erasing
				by overstriking with a space.  This allows
				terminals without the %TOERS capability to
				have display-style "rubout processing", as
				this capability depends upon either %TOERS
				or [%TOMVB and not %TOOVR].

%TOMVU		   400,,0	this terminal  is capable  of  moving  the
				cursor upwards.

%TOLWR		    20,,0	this  terminal's  keyboard is  capable  of
				generating lowercase characters;  this bit
				is mostly provided for programs which want
				to know this information.

%TOFCI		    10,,0	this  terminal's  keyboard is  capable  of
				generating  CONTROL and META characters as
				described below.

%TOLID		     2,,0	this  terminal  is  capable  of doing line
				insert/delete operations,  ie, it supports
				%TDILP and %TDDLP.

%TOCID		     1,,0	this   terminal   is   capable   of  doing
				character insert/delete operations, ie, it
				supports %TDICP and %TDDCP.
TTYOPT FUNCTION BITS (continued)

Bit name	Value		Meaning

%TPCBS		     0,,40	this terminal is  using  the  "intelligent
				terminal protocol".
				 THIS BIT MUST BE ON.

%TPORS		     0,,10	the server should  process  output  resets
				instead of ignoring them.
				 IT IS HIGHLY RECOMMENDED THAT THIS BIT BE
				ON; OTHERWISE THERE MAY BE LARGE DELAYS IN
				ABORTING OUTPUT.



The following bits are user  option bits.  They may be  set or not set  at
the user's discretion.  The bits that are labelled "normally on" are those
that are normally  set on when  a terminal is  initialized (ie, by  typing
[CALL] on a local terminal).

Bit name	Value		Meaning

%TOCLC		100000,,0	convert  lower-case  input to  upper case.
				Many  terminals  have  a  "shift lock" key
				which makes this option useless.
				 NORMALLY OFF.

%TOSA1		  2000,,0	characters  001-037  should  be  displayed
				using  the  Stanford/ITS  extended   ASCII
				graphics character set instead of  uparrow
				followed by 100+character.
				 NORMALLY OFF.

%TOMOR		   200,,0	the   system   should  provide  "**MORE**"
				processing when  the  cursor  reaches  the
				bottom  line  of  the  screen.    **MORE**
				processing is described in ITS TTY.
				 NORMALLY ON.

%TOROL		   100,,0	the terminal should scroll when attempting
				output below the bottom line of the screen
				instead of wrapping around to the top.
				 NORMALLY OFF.
INPUT -- THE INTELLIGENT TERMINAL PROTOCOL

Note: only  the parts  of the  intelligent terminal  protocol relevant  to
SUPDUP are discussed here.  For more information, read ITS TTY.


CHARACTER SETS

There are two  character sets  available for  use with  SUPDUP; the  7-bit
character set of standard ASCII, and the 12-bit character set of  extended
ASCII.  Extended ASCII has 5 high order  or "bucky" bits on input and  has
graphics for octal 000-037 and 177 (see the section entitled "Stanford/ITS
character set" for more details).  The two character sets are identical on
output since the protocol  specifies that the host  should never send  the
standard ASCII  formatting  characters  (ie,  TAB,  LF,  VT,  FF,  CR)  as
formatting characters; the characters whose  octal values are the same  as
these formatting characters are never output unless the user job has these
characters enabled (setting %TOSAI and %TOSA1 generally does this).

Input differs dramatically  between the 7-bit  and 12-bit character  sets.
In the 7-bit character set, all characters input whose value is 037  octal
or less  are assumed  to be  (ASCII) control  characters.  In  the  12-bit
character set,  there are  5 "bucky"  bits which  may be  attached to  the
character.  The two most  important of these are  CONTROL and META,  which
form a 9-bit character set.  TOP  is used to distinguish between  printing
graphics in the extended character set and ASCII controls.  The other  two
are reserved and should be ignored.  Since both 7-bit and 12-bit terminals
are commonly in use, 0001, 0301, and 0341 are considered to be  <CONTROL>A
on input by most programs, while 4001 is considered to be downwards arrow.


MAPPING BETWEEN CHARACTER SETS

Many programs and hosts do not process 12-bit input.  In this case, 12-bit
input is folded down to 7-bit as follows: TOP and META are discarded.   If
CONTROL is on, then if the 7-bit  part of the character specifies a  lower
case alphabetic it is converted to upper  case; then if the 7-bit part  is
between 077 and 137 the  100 bit is complemented or  if the 7-bit part  is
040 the 040 bit is subtracted  (that's right, <CONTROL>?  is converted  to
[RUBOUT] and <CONTROL>[SPACE] is  converted to [NULL]).   In any case  the
CONTROL bit is discarded,  and the remainder is  treated as a 7-bit  ASCII
character.  It should be noted that  in this case downwards arrow is  read
by the program as standard ASCII <CONTROL>A.

Servers which expect 12-bit input and are told to use the 7-bit  character
set should  do  appropriate unfolding  from  the 7-bit  character  set  to
12-bit.  It is up  to the individual server  to decide upon the  unfolding
scheme.  On ITS, user programs that use the 12-bit character set generally
have an alternative method for 7-bit; this often takes the form of  prefix
characters indicating that the next character should be "controllified" or
"metized", etc.
INPUT -- THE INTELLIGENT TERMINAL PROTOCOL (continued)


BUCKY BITS

Under normal circumstances, characters input from the keyboard are sent to
the foreign host as is.  There  are two exceptions; the first occurs  when
an octal 034  character is to  be sent; it  must be quoted  by being  sent
twice, because 034 is used as  an escape character for protocol  commands.
The second  exception occurs  when  %TOFCI is  set  and a  character  with
non-zero bucky bits is to be sent.  In this case, the character, which  is
in the 12-bit form:

Name	Value	Description

%TXTOP	4000	This character has the [TOP] key depressed.

%TXSFL	2000	Reserved, must be zero.

%TXSFT	1000	Reserved, must be zero.

%TXMTA	 400	This character has the [META] key depressed.

%TXCTL	 200	This character has the [CONTROL] key depressed.

%TXASC	 177	The ASCII portion of the character

is sent as three bytes.  The first  byte is always 034 octal (that is  why
034 must be  quoted).  The next  byte contains the  "bucky bits", ie,  the
%TXTOP through %TXCTL bits,  shifted over 7 bits  (ie, %TXTOP becomes  20)
with the 100  bit on.   The third  byte contains  the %TXASC  part of  the
character.  Hence the character <CONTROL><META>[LINE FEED] is sent as  034
103 012.


OUTPUT RESETS

The  intelligent  terminal  protocol  also  is  involved  when  a  network
interrupt (INR/INS) is  received by  the user program.   The user  program
should increment a count of received network interrupts when this happens.
It should not do any output, and if possible abort any output in progress,
if this count is greater than zero  (NOTE: the program MUST allow for  the
count to go less than zero).

Since the server  no longer  knows where the  cursor is,  it suspends  all
output until the user informs it of the cursor position.  This also  gives
the server an idea of how much was thrown out in case it has to have  some
of the aborted output  displayed at a later  time.  The user program  does
this when it  receives a  %TDORS from the  server.  When  this happens  it
should  decrement  the  "number  of  received  network  interrupts"  count
described in the previous paragraph and then send 034 followed by 020, the
vertical position,  and  the  horizontal  position  of  where  the  cursor
currently is located on the user's screen.
OUTPUT -- DISPLAY PROTOCOL (%TD CODES)

Display output  is  somewhat  simpler.   Codes less  than  200  octal  are
printing characters and  are displayed  on the terminal  (see the  section
describing the "Stanford/ITS character set").  Codes greater than or equal
to 200 (octal) are known as "%TD codes", so called since their names begin
with %TD.  The %TD codes that are relevant to SUPDUP operation are  listed
here.  Any other code  received should be ignored,  although a bug  report
might be sent  to the server's  maintainers.  Note that  the normal  ASCII
formatting characters (011 - 015) do NOT have their formatting sense under
SUPDUP and should not occur at all unless the Stanford/ITS extended  ASCII
character set is in use (ie, %TOSAI is set in the TTYOPT word).

For cursor  positioning operations,  the  top left  corner is  (0,0),  ie,
vertical position 0, horizontal position 0.

%TD code	Value		Meaning

%TDMOV		200		General cursor position code.  Followed by
				four bytes;  the  first  two are the "old"
				vertical  and horizontal positions and may
				be  ignored.    The  next  two are the new
				vertical  and  horizontal  positions.  The
				cursor  should be moved  to this position.

				On printing consoles (non %TOMVU), the old
				vertical position may differ from the true
				vertical position;  this  can  occur  when
				scrolling.  In this case, the user program
				should set  its  idea of the old  vertical
				position to what the %TDMOV says and  then
				proceed.  Hence a %TDMOV with an old  vpos
				of 20. and a new vpos of 22. should always
				move the "cursor" down two lines.  This is
				used to prevent the vertical position from
				becoming infinite.

%TDMV1		201		An  internal  cursor  motion  code   which
				should not be seen;  but if it is,  it has
				two  argument bytes after it and should be
				treated the same as %TDMV0.

%TDEOF		202		Erase  to  end  of  screen.   This  is  an
				optional function  since many terminals do
				not support this.   If  the terminal  does
				not  support this  function,  it should be
				treated the same as %TDEOL.

				%TDEOF does an erase to end of line,  then
				erases  all lines lower on the screen than
				the cursor.  The cursor does not move.

%TDEOL		203		Erase  to  end  of  line.  This erases the
				character position the  cursor  is at  and
				all  positions  to the right on  the  same
				line.  The cursor does not move.
OUTPUT -- DISPLAY PROTOCOL (%TD CODES) (continued)

%TD code	Value		Meaning

%TDDLF		204		Clear the character position the cursor is
				on.  The cursor does not move.

%TDCRL		207		If the cursor is not on the bottom line of
				the screen, move  cursor to  the beginning
				of the next line and clear that line.   If
				the  cursor is at the bottom line,  scroll
				up.

%TDNOP		210		No-op; should be ignored.

%TDORS		214		Output reset.   This code serves as a data
				mark for  aborting  output much as  IAC DM
				does in the ordinary TELNET protocol.

%TDQOT		215		Quotes the following  character.   This is
				used  when sending 8-bit codes  which  are
				not  %TD codes,  for instance when loading
				programs  into  an  intelligent  terminal.
				The  following  character should be passed
				through intact to the terminal.

%TDFS		216		Non-destructive forward space.  The cursor
				moves right one position;  this  code will
				not be sent at the end of a line.

%TDMV0		217		General cursor position code.  Followed by
				two bytes; the new vertical and horizontal
				positions.

%TDCLR		220		Erase the screen.   Home the cursor to the
				top left hand corner of the screen.

%TDBEL		221		Generate an audio tone, bell, whatever.

%TDILP		223		Insert blank lines at the cursor; followed
				by a byte containing a count of the number
				of blank lines to insert.   The  cursor is
				unmoved.   The line the cursor is  on  and
				all lines below it move down;  lines moved
				off the bottom of the screen are lost.

%TDDLP		224		Delete lines at the cursor;  followed by a
				count.  The cursor is unmoved.   The first
				line  deleted is the  one the cursor is on.
				Lines below those deleted move up.  Newly-
				created lines  at the bottom of the screen
				are blank.
OUTPUT -- DISPLAY PROTOCOL (%TD CODES) (continued)

%TD code	Value		Meaning

%TDICP		225		Insert  blank  character  positions at the
				cursor;  followed by  a count.  The cursor
				is unmoved.   The character the  cursor is
				on and all characters to the right  on the
				current line move to the right; characters
				moved off the end of the line are lost.

%TDDCP		226		Delete characters at the cursor;  followed
				by a count.   The cursor is unmoved.   The
				first  character  deleted  is the  one the
				cursor is on.  Newly-created characters at
				the end of the line are blank.

%TDBOW		227		Display black characters on white screen.
				HIGHLY OPTIONAL.

%TDRST		230		Reset %TDBOW and such any future options.
STANFORD/ITS CHARACTER SET

This section describes the extended  ASCII character set.   It  originated
with the character set developed at SAIL but was modified for 1968 ASCII.

This character set only  applies to terminals with  the %TOSAI and  %TOFCI
bits set in its TTYOPT word.  For non-%TOSAI terminals, the standard ASCII
printing  characters  are  the  only  available  output  characters.   For
non-%TOFCI terminals, the standard ASCII characters are the only available
input characters.


PRINTING CHARACTERS

The first table describes the printing characters.  For output, the  7-bit
code is sent (terminal operations are performed by %TD codes).  For input,
the characters with values 000-037 and 177 must have the %TXTOP bit on  to
indicate the graphic is intended rather than a function or ASCII control.

Value	Character

 4000	centered dot
 4001	downward arrow
 4002	alpha
 4003	beta
 4004	logical AND
 4005	logical NOT
 4006	epsilon
 4007	pi
 4010	lambda
 4011	gamma
 4012	delta
 4013	uparrow
 4014	plus-minus
 4015	circle-plus
 4016	infinity
 4017	partial delta
 4020	proper subset (left horseshoe)
 4021	proper superset (right horseshoe)
 4022	intersection (up horseshoe)
 4023	union (downward horseshoe)
 4024	universal quantifer
 4025	existential quantifier
 4026	circle-X
 4027	double arrow
 4030	left arrow
 4031	right arrow
 4032	not-equal
 4033	lozenge (diamond)
 4034	less-than-or-equal
 4035	greater-than-or-equal
 4036	equivalence
 4037	logical OR
 0040	first standard ASCII character (space)
  ..		. . .
 0176	last standard ASCII character (tilde)
 4177	integral
STANFORD/ITS CHARACTER SET (continued)


FUNCTION KEYS AND SPECIAL CHARACTERS

In addition, the following special characters exist for input only.  These
characters are  function keys  rather than  printing characters;  however,
some of these  characters have some  format effect or  graphic which  they
echo as; the host, not the SUPDUP program, handles any such mappings.

Value	Character	Usual echo		Usual Function

 0000	[NULL]
 0010	[BACK SPACE]				text formatting
 0011	[TAB]					text formatting
 0012	[LINE FEED]				text formatting
 0013	[VT]					text formatting
 0014	[FORM]					text formatting
 0015	[RETURN]				text formatting
 0032	[CALL]		uparrow-Z		escape to system
 0033	[ALTMODE]	lozenge or $		special activation
 0037	[BACK NEXT]	uparrow-underscore	monitor command prefix
 0177	[RUBOUT]				character delete

 4101	[ESCAPE]				local terminal command
 4102	[BREAK]					local subsystem escape
 4103	[CLEAR]
 4110	[HELP]					requests a help message


BUCKY BITS

For all input characters, the following  "bucky bits" may be added to  the
character.  Their interpretation depends entirely upon the host.  <TOP> is
not listed here, as it  has been considered part  of the character in  the
previous  tables.

<CONTROL> is different from ASCII CTRL, however, many programs may request
the operating system to map such  characters to the ASCII forms (with  the
<TOP> bit off).  In this case <META> is ignored.

Value	Key

 2000	Reserved
 1000	Reserved
 0400	<META>
 0200	<CONTROL>
ACKNOWLEDGEMENTS

Richard M. Stallman (RMS@MIT-AI)  and David A.  Moon (Moon@MIT-MC) of  the
MIT-AI and MIT-MC  systems staff  wrote the source  documentation and  the
wonderful ITS terminal support that made this protocol possible.  It  must
be emphasized  that  this is  a  functional  protocol which  has  been  in
operation for some years now.

In addition, Moon,  Stallman, and Michael  McMahon (MMcM@SRI-KL)  provided
many helpful comments and corrections to this document.

For further reference, the sources for the known currently existing SUPDUP
user programs are available online as:

[MIT-AI] SYSENG;SUPDUP >		for the ITS monitor,
[SU-AI]  SUPDUP.MID[NET,MRC]		for the SAIL monitor,
[SRI-KL] <MMcM>SD.FAI			for the TOPS-20 monitor.

The source for the known currently existing SUPDUP server program is:

[MIT-AI] SYSENG;TELSER >		for the ITS monitor.

These programs  are written  in  the MIDAS  and  FAIL dialects  of  PDP-10
assembly language.
SUPDUP.MRC[UP,DOC]

		SUPer-DUPer Display TELNET to ITS
			  Mark Crispin

 INTRODUCTION:

SUPDUP is the SAIL implementation of the ITS SUPDUP program, which is used
for TELNETing  between ITS  sites.   This program  uses the  internal  ITS
display codes  for highly  efficient  communication and  full use  of  ITS
display programs over the ARPAnet.  In addition, SUPDUP allows the user to
send the full  ITS ASCII  character set  (which includes  some very  hairy
characters!) and maps  both keyboard input  and display output  so that  a
Stanford display (DD, III, or DM) appears as a funny kind of ITS display.

SUPDUP also runs on printing consoles; on these ↑↑ enters command mode.

When SUPDUP is run,  it will prompt  for the host name.   Type one or  two
characters to identify the name  of the ITS system  you wish to TELNET  to
(ie, either  "A", "D",  "MC", and  "ML").  SUPDUP  will then  establish  a
connection  with  the  specified  ITS  site,  and  after  that  you   will
effectively be a display on ITS, with full bucky bit capability.

Some mappings in input and output are made due to the differences  between
the SAIL  and  ITS ASCII  character  sets.   Most of  these  mappings  are
transparent to the user.  The design philsophy behind the mappings was  to
cause characters typed on the Stanford keyboard  to be seen by ITS as  the
character appears on the key tops, and for characters received from ITS to
be displayed as they would be at a console at MIT.

NOTE!!!:

One thing that I should mention: you MUST NOT do a :TCTYP on ITS that will
set your terminal type.  SUPDUP's operation depends upon the terminal type
being SOFTWARE and things will not work correctly if it is set to anything
else.  It  is alright  to set  certain other  TCTYP options  such as  SAIL
character set enable, however, in general you probably will not want to do
any TCTYP  at all.   SUPDUP sets  the line  length and  page size  to  the
maximum possible on the screen.
 SUPDUP FEATURES:

  Visible OUTPUT MAPPINGS:

Caret is  mapped to  AND sign  (∧)  since there  is no  code in  the  SAIL
character set for caret.   There is no  way to tell  between AND sign  and
caret.  In addition, centered-dot, gamma,  delta, and circle-plus are  not
displayed (they generate an error message).

  Visible INPUT MAPPINGS:

αz and αZ are mapped to [CALL], αβz  and αβZ are mapped to α[CALL]; α_  is
mapped to [BACK NEXT] and  αβ_ is mapped to β[BACK  NEXT]. ↑ is mapped  to
caret; to send ↑  (distinct from VT) see  below.  Some other more  obscure
characters must be sent by using a command; see below.

  COMMANDS:

[ESCAPE]I is used to enter a  SUPDUP command.  The following commands  are
defined:

	F	Use Fast display mode (discussed below).
	K or L	Kill the job on ITS and break network connections.
	P	Temporarily restore the page printer.  Typing any
		 character will return your screen to ITS.
	Q	Quit out, close network connections, detach the job
		 on ITS if there is one.
	R	Record contents of screen onto a file; asks you for
		 name of file to write.  REENTER does this too.
	S	Use Slow display mode (see below).
	V	Re-draw the current screen.
	?	Type a help text.

Command mode also allows  some of the more  esoteric ITS characters to  be
sent.  For example, ↑, α↑, β↑, αβ↑, αz, αβz, αZ, αβZ, α_, and αβ_ are sent
in image mode without being mapped.   Special mappings exist for keys  not
on the keyboard or trapped  by the monitor.  They  may be sent with  bucky
bits, and  they have  no explicit  graphic here  or on  ITS, as  they  are
special function keys.  These are:

 .	centered-dot	[TAB]	gamma		[LF]	delta
 [CR]	circle-plus	[BS]	integral	∂	[NULL]
 λ	[BACK SPACE]	≠	[CALL]		∨	[BACK NEXT]
 α	[ESCAPE]	β	[BREAK]		ε	[CLEAR]

DISPLAY MODES:

SUPDUP has two display modes; fast and slow, which are set by the F and  S
commands.  Fast mode, which is the  default, is highly optimal on  network
input  and  very  fast  on  display.   On  the  other  hand,  it  can   be
disconcerting to have  the screen  flash as suddenly  as it  does with  no
semblance  of   line-  per-line   output  (it   sort  of   comes  out   as
chunk-per-chunk), therefore, there is a  slow mode which causes SUPDUP  to
output in the old-fashioned manner which just does normal optimization but
not line/screen optimization.
 Everything nobody wanted to know about SUPDUP's internal mappings

The following character set mappings are in effect.  These mappings  occur
on both input and output,  so in general they  are invisible to the  user.
In particular, the graphic on the keytop is what ITS will see, and what is
displayed on the screen is what would be displayed on an ITS TV.  But  see
the second table and notes for exceptions.

	SAIL		ITS
	----		---

  013	 VT		 ↑	(6)

  030	 _		 ←

  032	 ~		 ≠

  033	 ≠		ALT

  136	 ↑		 ∧	(2)

  137	 ←		 _

  175	ALT		 }

  176	 }		 ~

  177	BS		INT	(1) (6)


 In addition, the following keyboard mappings are done:

	KBD code	Sent to ITS
	--- ----	---- -- ---

	   αz		   [CALL]	(3)

	   αZ		   [CALL]

	  αβz		  α[CALL]

	  αβZ		  α[CALL]

	   α_		 [BACK NEXT]	(4)

	  αβ_		α[BACK NEXT]

	    ↑		     ∧		(2) (5)

 Notes:

(1) This character  is image rubout,  which on  a PDP-11 TV  is output  as
integral sign.

(2) AND sign  (∧) is used  for caret since  there is no  code in the  SAIL
character set for caret anyway.

(3) These four mappings are necessary since there is no way that any  form
of [CALL] can be read by a user program.

(4) This mapping is necessary since there is no key remotely equivalent to
the [BACK NEXT] key.

(5) This mapping  is necessary since  otherwise there is  no way to  enter
caret from the  keyboard.  As  caret is more  important on  ITS, up  arrow
lost.  VT  will input  an up-arrow,  however it  will not  be  [TOP]ified,
meaning that in order  to enter this  character into TECO  one must use  a
quoting convention  or  up-arrow  as  a command;  see  previous  page  for
details.

(6) Output only mapping.

⊗
subttl ITS TTY definitions

;  These definitions are the various bits, words, etc. for the ITS terminal
; service system calls and are here for convenience and clarity.  This is
; abridged from [MIT-AI] SYSTEM;BITS >, the monitor bits definition file.

; TTYOPT variable (terminal capabilities)

sdttop==0				; for initial value

; Macro to specify that this bit is used by SUPDUP

define use def/
 def
 irps bit,,[def]
  sdttop==sdttop\bit
  .istop
 termin
termin

    %toalt==200000,,			; 1 → standardise altmodes
    %toclc==100000,,			; 1 → convert cases on input
use %toers==040000,,			; 1 → this terminal can erase
    %tohdx==020000,,			; 1 → half duplex
use %tomvb==010000,,			; 1 → can backspace
use %tosai==004000,,			; 1 → has SAIL graphics
use %tosa1==002000,,			; 1 → init %TSSAI in new jobs (use graphics)
    %toovr==001000,,			; 1 → can overprint
use %tomvu==000400,,			; 1 → can line starve (ie a display)
use %tomor==000200,,			; 1 → do **More** processing (init %TSMOR)
    %torol==000100,,			; 1 → scroll (init %TSROL for new jobs)
    %toraw==000040,,			; 1 → no cursor motion optimization
use %tolwr==000020,,			; 1 → lower case keyboard
use %tofci==000010,,			; 1 → has bucky bit keyboard
    %toiml==000004,,			; 1 → acts like a grIMLAC (funny ↑PF, ↑PB)
use %tolid==000002,,			; 1 → can insert/delete lines
use %tocid==000001,,			; 1 → can insert/delete characters
    %tpplf==700000			; LF padding
    %tppcr==070000			; CR padding
    %tpptb==007000			; TAB padding (0 → no tabs, 1 → tabs)
    %tptel==000100			; 1 → CR → CRLF for ARPAnet protocol
use %tpcbs==000040			; 1 → intelligent terminal protocol (↑\)
    %tp11t==000020			; 1 → PDP-11 TV (reflects %TY11T)
use %tpors==000010			; 1 → output reset should do something
    %tpibc==000002			; 1 → correspondence code 2741
    %tpibm==000001			; 1 → IBM 2741

; TCTYP variable (terminal type)

%tnprt==0				; printing console, glass TTY, etc.
%tndp==1				; good Datapoint
%tnodp==2				; inferior losing Datapoint
%tniml==3				; grIMLAC
%tntek==4				; Tektronix 4000 series
%tntv==5				; PDP-11 TV
%tnmem==6				; Memowreck
%tnsfw==7				; Software
%tntrm==10				; Terminet
%tnesc==11				; ASCII standard display (VT52, etc.)
%tndtm==12				; Datamedia 2500
%tnmax==13				; 1 + largest terminal type

; Components of an input character in 12-bit mode.

%txasc==0177				; ASCII part
%txctl==0200				; control
%txmta==0400				; meta
%txsft==1000				; shift
%txsfl==2000				; shift lock
%txtop==4000				; top
SUBTTL ITS output buffer codes

; These are the ITS output buffer codes (used by Software terminals).

%tdmov==200				; move cursor OV OH NV NH
%tdmv1==201				; move cursor; NV NH
%tdeof==202				; clear to end of screen
%tdeol==203				; clear to end of line
%tddlf==204				; delete character after cursor
%tdmtf==205				; motor off
%tdmtn==206				; motor on
%tdcrl==207				; terpri
%tdnop==210				; no-op
%tdbs==211				; backspace
%tdlf==212				; line feed
%tdrcr==213				; carriage return
%tdors==214				; output reset
%tdqot==215				; quote next character (mystery command)
%tdfs==216				; cursor forward
%tdmv0==217				; move cursor NV NH
%tdclr==220				; clear screen
%tdbel==221				; feep!
%tdini==222				; reset reset reset
%tdilp==223				; insert line; count
%tddlp==224				; delete line; count
%tdicp==225				; insert character; count
%tddcp==226				; delete character; count
%tdbow==227				; inverse video
%tdrst==230				; reset inverse video, etc.
%tdmax==231				; 1 + largest display code
subttl SAIL system definitions

;  First define all the UUO's.  MIDAS has these predefined, but DDT is
; cretinous.

.insrt SAIDFS[CSP,SYS]
.decdf

;  This page contains the SAIL system bits that are used within SUPDUP.  It is
; not a complete list of the SAIL system bits.

; SETACT bits

allact==000040				; all αβ characters and BS activate
bsact==	000020				; all forms of BS activate
supscm==000004				; all αβ characters activate
supccr==000002				; αCR is an ordinary character

; GETLIN/SETLIN bits

dislin==400000,,			; terminal is a III
dmlin==	040000,,			; terminal is a DM
dddlin==020000,,			; terminal is a DD
echarr==010000,,			; terminal echoes arrow for controls
ptylin==004000,,			; terminal is a PTY
impbit==001000,,			; terminal is controlled by a network job
spcbrk==000100,,			; terminal is in special activation mode

; Interrupt condition bits

inttty==020000,,			; TTY input activation
intclk==000200,,			; clock interrupt
intinr==000100,,			; IMP INR
intins==000040,,			; IMP INS
intims==000020,,			; IMP status change
intinp==000010,,			; IMP input waiting
inttti==000004,,			; [ESCAPE]I

; DM UPGIOT flags

trunca==040000,,			; truncate output lines to 80. characters
noeeol==020000,,			; suppress CEOL when moving to a line
noeeob==010000,,			; suppress CEOL on blank line

; Network socket status flags

rfcs==	200000,,			; RFC sent
rfcr==	100000,,			; RFC received
clss==	040000,,			; CLS sent
clsr==	020000,,			; CLS received

; Network I/O status bits

hdead==	002000				; host or destination IMP dead
ctrov==	001000				; host sent more bits than allocated
rset==	000400				; host sent a RST
tmo==	000200				; time out

; Network status word error codes

siu==	01				; socket in use
ccs==	02				; can't change socket numbers
sys==	03				; horrible system error
nla==	04				; no links available
ilb==	05				; illegal byte size
idd==	06				; IMP dead
gmm==   07				; gender mismatch (homosocketual connection)

; I/O status word error bits

ioimpm==400000				; improper mode
ioderr==200000				; hard device error (data missed, etc.)
iodter==100000				; soft device error (parity error, etc.)
iobktl==040000				; block number out of bounds
iodend==020000				; end of file

];if1
subttl Data area

.ystgw					; storage words okay now

; Beginning of core area initialized to zero at startup

corbeg==.				; beginning of data area

cnsblk:	block 1				; CNSGET info
tctyp:	block 1				; TCTYP for server
ttyopt:	block 1				; TTYOPT for server
tcmxv:	block 1				; TTY page length
tcmxh:	block 1				; TTY width
ttyrol:	block 1				; TTYROL variable
cnsbll==.-cnsblk

; Random flags

dmp:	block 1				; -1 → this is a Datamedia
dmluzp:	block 1				; -1 → this is a non-FCS (losing) Datamedia
ddp:	block 1				; -1 → this is a Data Disc
iiip:	block 1				; -1 → this is a III
ptyp:	block 1				; -1 → this is a PTY
netp:	block 1				; -1 → this is a network PTY
filinp:	block 1				; -1 → fill in host name
runcmp:	block 1				; -1 → called via RUN command
slowip:	block 1				; -1 → do input slow way
clsedp:	block 1				; -1 → connection closed by foreign host
imgchp:	block 1				; -1 → image characters from command
ntbfop:	block 1				; -1 → output to net in buffer

; Interrupt level flags

ttiinp:	block 1				; -1 → TTY input pending
ntiinp:	block 1				; -1 → net input pending
ntoinp:	block 1				; <0 → INS pending

; Buffer headers

ntibf:	block 3				; net input buffer header
ntobf:	block 3				; net output buffer header
dsibf:	block 3				; disk input buffer header
dsobf:	block 3				; disk output buffer header

; Other random storage

lgrskt:	block 1				; socket from logger
pdl:	block pdllen			; pushdown stack
ttynum:	block 1				; our TTY number
ttystr:	block 11.			; TTY string
; IMP MTAPE command words

; Connect to host command block

impcod:	block 1				; command
impsta:	block 1				; status
implsk:	block 1				; local socket
impwat:	block 1				; ≠ 0 → wait for connection
impbyt:	block 1				; byte size
impfsk:	block 1				; foreign socket
imphst:	block 1				; foreign host number

; Wait for connection to be completed command block

watcod:	block 1				; command
watsta:	block 1				; status
watskt:	block 1				; socket

; Close connection to host command block

clscod:	block 1				; close code
clssta:	block 1				; close status
clsskt:	block 1				; close socket
clswat:	block 1				; ≠ 0 → wait for close
subttl Display crufties

; Number of words in display frobs

nwrdln==4+nchars/5			; number of words on a line
scrsiz==nlines*nwrdln			; number of words on screen
ngw==<<nchars*3>+17.>/16.		; number of graphics words

; Cursor position pointers

vpos:	block 1				; vertical position
hpos:	block 1				; horizontal position
ovpos:	block 1				; old vertical position

; Positioning flags

govpos:	block 1				; -1 → get old vertical position
gohpos:	block 1				; -1 → get old horizontal position
gtvpos:	block 1				; -1 → get vertical position
gthpos:	block 1				; -1 → get horizontal position

; Insert/delete mode flags

gtiln:	block 1				; -1 → get # of lines to insert
gtdln:	block 1				; -1 → get # of lines to delete
gtich:	block 1				; -1 → get # of characters to insert
gtdch:	block 1				; -1 → get # of characters to delete

; Screen updating flags

slupdp:	block nlines			; -1 → this line has changed
scupdp:	block 1				; -1 → some update happened someplace
saupdp:	block 1				; -1 → updated whole screen
crupdp:	block 1				; -1 → updated cursor

corend==.-1				; address of top of core

; End of core zeroed upon startup

debugp:	block 1				; -1 → debugging

; Various display programs

; III header word

iiihdr:
.byte 11.,11.,3.,3.,2.,2.,4.
 -777 ? 640 ? 4 ? 2 ? 1 ? 2 ? 6		; invisible absolute vector
.byte

; Display screen display program

scp:	ddcmd 1,46,4,1,5,10		; line address 30
	ddcmd 3,2,3,2,3,2		; go to column 2
screen:	block scrsiz			; TV screen storage
scrend=.-1				; end of screen storage
	0				; end of DD program
scpl==.-scp
botlin=screen+scrsiz-nwrdln+2-1		; address of start of bottom line
; More display data stuff

; Display cursor display program

scc:	ddcmd 1,7,1,7,1,7		; graphics
	ddcmd 3,1,4,0,5,0		; select position
	block ngw			; all graphics columns
	ddcmd 0,0,1,46,1,46		; execute
	0				; end of program
sccl==.-scc

; Line display programs

linprg:	ddcmd 1,46,4,0,5,0		; line update commands
	ddcmd 3,2,3,2,3,2
	block nwrdln-3
	0

; Display commands

; Display screen

sdisp:	600000,,scp			; two field mode
	scpl				; size of display program
	0				; no transfer in progress flag
	scp				; address of low order line command

; Cursor display

cdisp:	400000,,scc			; address of cursor hacker
	sccl				; size of the hacker
	0				; transfer in progress flag
	scc+1				; address of low order line command

cclear:	scc				; address of cursor hacker
	sccl				; size of the hacker
	0				; no transfer in progress flag
	scc+1				; address of low order line command

; Line display

ldisp:	600000,,linprg			; two field mode
	nwrdln				; size of this command
	0 ? linprg			; t-i-p flag

; Byte pointer table for insertions

scbytp:	350700,,(y)
	260700,,(y)
	170700,,(y)
	100700,,(y)
	010700,,(y)

; DM display programs and stuff

dmdisp:	trunca\noeeol\noeeob+dmpgm	; truncate, no ceol
	0 ? 0				; # words, t-i-p flag

dmpgm:	block dmbufl			; DM display program

dmcnt:	0				; DM program counter
dmpnt:	0				; DM program counter
subttl UUO server

; UUO server.  Only allows BURP UUO (op code 037).

; BURP	[OP=037]
; --------------------------------------------------
;	BURP ADR
;
; ADR:	<asciz string>
;
; The BURP UUO types out the ASCIZ string that starts at location ADR.
; message.  If the DEBUGP runtime switch is set, BURP bops into DDT if
; DDT is present; RETURN[ALT]X from DDT attempts to return.  BURP should
; not be called from interrupt level.
; A non-zero AC field means the error is fatal.

BURP=037000,,				; UUO for logging cruft
BARF=burp 1,				; UUO for fatalities

pgmbeg==.				; start of pure core

tmploc job41,call uuoser		; UUO server

uuoser:	save t ? save u			; save the old UUO AC's
	save jobuuo			; and the UUO itself
	ldb u,[.bp %icopc,jobuuo]	; get op code
	caxe u,burp←-27.		; was it a BURP UUO?
	 barf [asciz/Illegal UUO!
/]					; isn't recursion wonderful?
	ldb u,[.bp %icacf,jobuuo]	; get AC field
	outstr @(p)			; type the message
	skipn u				; fatal error?
	 skipe debugp			; debugging?
	  call ddtcal			; yes, call DDT
	adjsp p,-3			; drop stack
	return				; return to user

; Call DDT

ddtcal:	call echon			; turn echoing back on
	skipn u,jobddt			; get start addr of DDT
	 jrst [	exit 1,			; no DDT!!!
		jrst ddtret]		; continue...
	outstr [asciz/You're in DDT.
/]
	call (u)			; call DDT
ddtret:	ptjobx [0 ? sixbit/DOFF/]	; turn echoing off
	ppact				; flush PP
	store %fword,saupdp		; must fix whole screen
	leypos 2000			; throw away line editor
	return				; and return

; Turn echoing back on (this so it can be called from bkpt)

echon:	ptjobx [0 ? sixbit/DON/]	; turn echoing on
	hrroi t,[004000,,400\"N]	; [BREAK]N
	ttyset t,
	return				; return to caller
subttl Interrupt server

intser:	movn x,jobcni			; -reason
	andca x,jobcni			; set to 0 iff only one bit set
	jumpn x,mulint			; lossage!
	skipn x,jobcni			; get reason for interrupt
	 jrst noint			; no interrupt set?
	txze x,intclk			; clock int?
	 txo x,inttty\intinp		; yes, fake TTI and NTI int
	txze x,inttty			; TTY int?
	 store %fword,ttiinp
	txze x,intinp			; network interrupt?
	 store %fword,ntiinp
	txze x,intins			; IMP INS?
	 sos ntoinp
	txze x,inttti			; [ESCAPE]I?
	 jrst [	intmsk [%zeros]		; don't let interrupts happen
		uwait			; get AC's back, finish UUO
		debreak			; leave int level
		save jobtpc		; return PC
		insirp save,x y z
		call cmdcmd		; do command
		insirp retr,z y x
		intmsk [%fword]		; interrupts okay again
		return]
	txze x,intims			; IMP status change?
	 store %fword,clsedp
	jumpn x,uknint			; known interrupt?
	dismis				; yes, dismiss the interrupt
	
; Interrupt-level errors

uknint:	outstr [asciz/Unknown interrupt!
/]
	jrst intluz

mulint:	outstr [asciz/More than one interrupt bit set!
/]
	jrst intluz

noint:	outstr [asciz/Interrupt with no interrupt bits!
/]
;	jrst intluz

intluz:	uwait				; finish UUO, restore AC's
	save jobtpc			; save PC of interrupt
	intmsk [%zeros]			; forbid interrupts
	debreak				; enter user mode
	call ddtcal			; now enter DDT
	intmsk [%fword]			; allow interrupts again
	return				; return to interrupted program
subttl Startup, etc.

;  Initialize the world; clear all I/O and other things; give
; back any unneeded core to the monitor; clear data area, and
; set up the stack pointer.

supdup:	jfcl				; flush CCL crufties
	reset				; reset all I/O
	skipe debugp			; debugging?
	 outstr [asciz/Debugging version!
/]
	movei intser			; get addr of interrupt server
	movem jobapr			; tell monitor
	hlrz jobsa			; get size I should be
	skipn debugp			; debugging?
	 movei sdpff			; no, then okay to flush DDT
	hrlm jobsa			; but make sure monitor knows now
	movem jobff			; make sure monitor knows
	core				; in case I grew
	 barf [asciz/CORE UUO failed!
/]					; goddam ungrateful monitor!
	skipe debugp			; debugging?
	 jrst supdp1			; yes, can't flush DDT
	hrrz jobddt			; get addr of DDT
	caige sdpff			; it is below pgm?
	 jrst supdp1			; yes, didn't flush DDT
	movx x,%zeros			; no, flushed DDT, flush DDT's start addr
	setddt x,			; tell monitor (sigh)
supdp1:	store %zeros,corbeg,corend	; clear data area
	setzb @jobff			; clear first word of garbage
	adjsp @jobff			; make zapping pointer
	aos				; point to next word
	blt @jobrel			; now flush this trash
	move p,[pdl(-pdllen)]		; load PDP

; (continued on next page)
; Initial terminal setup

; Set up terminal codes for ITS and the sort of display we are

	store <<1-cnsbll>,,>,cnsblk	; Moon's new protocol
	store %tnsfw,tctyp		; software TTY
	store sdttop,ttyopt		; what we can support
	store nlnglt,ttyrol		; scroll count
	move [-2,,[6000,,tcmxh ? 15000,,tcmxv]]
	ttyset				; get screen size information
	sos tcmxv ? sos tcmxv		; don't garble who-line
	sos tcmxh			; also allow for "!" on line overflow

;  Check terminal characteristics

	movx x,%fword			; my console
	getlin x			; get my line characteristics
	caxn x,%fword			; detached?
	 exit				; yes, die die die
	hrrzm x,ttynum			; save console number
	txne x,ptylin			; a PTY?
	 store %fword,ptyp		; what a pity (I like puns)
	skipge tcmxv			; really PTYful?
	 jrst @sdpprt			; yes, don't claim to be a display
	txne x,dislin			; III?
	 store %fword,iiip		; yes
	txne x,dddlin			; Data Disc?
	 store %fword,ddp		; yes
	txne x,dislin\dddlin		; is this a local display?
	 jrst sdpdpy			; yup, it's a display
	txnn x,dmlin			; Datamedia?
sdpprt:	 jrst [	movei ['SYS,, ? 'TELNET ? 0 ? 0 ? 0 ? 0]
		run			; printing console, use TELNET instead
		 jrst 4,.-1]		; RUN failed?
	txnn x,impbit			; IMP PTY?
	 jrst nothop			; nope
	store %fword,netp		; net hopper!
	outstr [asciz/Foo you are a net hopper.
/]
nothop:	store %fword,dmp		; yes
	hrroi [21000,,y]		; Datamedia state flags
	ttyset				; (right half of DMFLAG in DPY header)
	txnn y,4000			; bit 2.3 → FCS DM
	 sosa dmluzp			; nope, loser
	  jrst sdpdpy			; now continue
	movx y,%tosai\%tosa1		; FCS bits
	andcam y,ttyopt			; tell ITS we don't have SAIL graphics

; Set terminal activate on all characters

sdpdpy:	txo x,spcbrk			; special activation mode bit
	setlin x			; enter SAM
	setact [[777777,,777777		; activate on 000 - 043
		 777777,,777777		;  044 - 107
		 777777,,777777		;  110 - 153
		 777777,,600000\allact\bsact\supscm\supccr]]; 154 - 177, αβ act
	ptjobx [0 ? sixbit/DOFF/]	; turn echoing off
;	jrst chfhnm			; now check for host name
subttl Monitor command processor

;  Check for host name in the monitor command line.  Yes, I realize this
; code is totally wierd!!!

chfhnm:	rescan x			; get monitor command cruft back
	jumpe x,gethst			; no cruft, ask for it
moncom:	inchrs x			; got a command, gobble a character
	 jrst gethst			; lost, do it manually
	caxl x,"a			; lower case?
	 caxle x,"z			; . . .
	  caxa				; no
	   subx x,"a-"A			; yes, uppercaseify
	skipn runcmp			; already checked for RUN command?
	 jrst [	caxe x,"R		; is it a RUN command?
		 aosa runcmp		; nope
		  store %fword,runcmp	; yes, no spaces checked!
		jrst .+1]		; now return
	skipl runcmp			; called via RUN command?
	 caxe x,<" >			; space frob? (only if not RUN)
	  caxn x,<";>			; or comment?
	   caxa				; yup, hack it
	    jrst moncom			; haven't gotten there yet, try again
	move b,[jsp y,[	inchrs x	; yes, load subroutine
			 jrst badhst	; lost
			caxl x,"a	; lower case?
			 caxle x,"z	; . . .
			  caxa		; no
			   subx x,"a-"A	; yes
			caxn x,<" >	; found space?
			 jrst -1(y)	; yes, flush it
			jrst (y)]]	; end of subroutine
	jrst scnhst			; and scan for this host
subttl Get host name

gethst:	outstr [asciz/Host = /]
	move b,[jsp y,[	inchrw x	; subroutine for non-monitor command
			caxl x,"a	; lower case?
			 caxle x,"z	; . . .
			  caxa		; no
			   subx x,"a-"A	; yes, uppercaseify
			outchr x	; echo the whatever
			jrst (y)]]	; end of non-monitor subroutine
	store %fword,filinp		; remember to fill in host name
scnhst:	xct b				; get a character
	caxn x,"A			; AI Lab?
	 jrst [	skipe filinp		; fill in host name?
		 outstr [asciz/I
/]
		movx a,sixbit/SD AI/	; select host name
		setnam a,		; and tell monitor
		movx a,206		; MIT-AI
		jrst goicp]		; now ICP
	caxn x,"D			; Dynamod?
	 jrst [	skipe filinp		; fill in host name?
		 outstr [asciz/M
/]
		movx a,sixbit/SD DM/	; select host name
		setnam a,		; and tell monitor
		movx a,106		; MIT-DMS
		jrst goicp]		; now ICP
	caxn x,"S			; SAIL?
	 jrst [	skipe filinp		; fill in host name?
		 outstr [asciz/AIL
/]
		movx a,sixbit/SD SU/	; select host name
		setnam a,		; and tell monitor
		movx a,13		; SU-AI
		jrst goicp]		; now ICP
	caxe x,"M			; MathLab LCS place?
badhst:	 jrst [	outstr [asciz/?
/]
		clrbfi			; flush input buffer
		jrst gethst]
	xct b				; get another character
	caxl x,"a			; lower case?
	 caxle x,"z			; . . .
	  caxa				; no
	   subx x,"a-"A			; uppercaseify
	caxn x,"C			; MACSYMA consortium?
	 jrst [	movx a,sixbit/SD MC/	; select host name
		setnam a,		; and tell monitor
		movx a,354		; MIT-MC
		skipe filinp		; filling in?
		 outstr [asciz/
/]
		jrst goicp]		; now ICP
	caxe x,"L			; Autoprog?
	 jrst badhst			; nope, losey
	movx a,sixbit/SD ML/		; select host name
	setnam a,			; tell monitor
	movx a,306			; MIT-ML
	skipe filinp			; filling in?
	 outstr [asciz/
/]
;	jrst goicp			; now ICP
subttl ICP ICP ICP

goicp:	clrbfi				; clear any crlf, etc.
	outstr [asciz/ Trying... /]

; Open channels and set timeouts

	init icp,17			; open ICP in dump mode
		'IMP,,			; ARPAnet
		0			; no buffers
	 barf [asciz/Can't OPEN the IMP!
/]
	mtape icp,[	17		; set timeouts
			.byte 6 ? 1 ? 0 ? 0 ? 15.? 5 ? 0]
	init net,0			; open NET in ASCII mode
		'IMP,,			; ARPAnet
		ntobf,,ntibf		; buffers
	 barf [asciz/Can't OPEN the IMP!
/]
	mtape net,[	17		; set timeouts
			.byte 6 ? 1 ? 15. ? 0 ? 5 ? 0 ? 0]

;  Try to generate a unique socket number, using job number and
; time of day to avoid lossage due to old connections.
; Algorithm used is: job #,,<time&777770>

	pjob x,				; get my job #
	mstime y,			; and the time now
	lsh x,18.			; put job # in LH
	hrri x,(y)			; and time in RH
	andx x,37777777770		; but zap low order bits

; Now try to get to the foreign place's server

insirp setzm,[impcod impsta impbyt]
	store %fword,impwat		; do wait until timeout
	movem x,implsk			; my socket to use
	movem x,clsskt			; socket to close when done
	movem a,imphst			; host to go to
	store icpskt,impfsk		; socket to ICP on
	mtape icp,impcod		; connect → foreign logger
	move x,impsta			; get status
	txne x,77			; error code?
	 jrst conerr			; yes, report MTAPE lossage
	getsts icp,y			; get error stats for message
	txne y,ioimpm\ioderr\iodter\iobktl\iodend\hdead\ctrov\rset\tmo
	 jrst iioerr			; so sorry
	txc x,rfcs\rfcr			; for next instruction to win
	txne x,rfcs\rfcr		; RFC sent+received?
	 jrst [	txne x,clss\clsr	; close sent?
		 jrst refuse		; yes, refused
		movx y,tmo		; no, fake time out
		jrst iioerr]		; and output error message
	hrroi y,impfsk-1		; get ready to get a word
	movx z,%zeros			; stop after

; (continued on next page)
; Get socket number from logger

	in icp,y			; get socket from logger
	 caxa				; won
	  jrst nosock			; didn't get socket number!
	ldb x,[044000,,impfsk]		; get socket we got
	movem x,impfsk			; and save it back
	store 3,clscod			; close code
	mtape icp,clscod		; close off ICP socket
	releas icp,			; free up channel

; Got socket number from logger; now connect output

	movx x,3			; ICP/transmit offset
	addb x,implsk			; local transmit socket
	movem x,watskt			; save wait socket
	store %zeros,impwat		; don't wait
	store 8.,impbyt			; byte size
	mtape net,impcod		; connect → server output
	move x,impsta			; get status
	txne x,77			; only error code
	 jrst conerr			; error?

; Now connect input

	sos implsk			; local receive socket
	aos impfsk			; foreign transmit socket
	mtape net,impcod		; connect ← server input
   	move x,impsta			; get status
	txne x,77			; only error code
	 jrst conerr			; lose lose lose

; Connections started, now wait for output

	store 4,watcod			; WAIT code
	mtape net,watcod		; wait for output
	move x,watsta			; get status
	txne x,77			; only error code
	 jrst conerr			; lose lose lose
	getsts net,y			; get error bits for message
	txne y,ioimpm\ioderr\iodter\iobktl\iodend\hdead\ctrov\rset\tmo
	 jrst iioerr			; too bad
	txc x,rfcs\rfcr			; for next instruction to win
	txne x,rfcs\rfcr		; RFC sent+received?
	 jrst [	txne x,clss\clsr	; close sent?
		 jrst refuse		; yes, refused
		movx y,tmo		; no, fake a time out
		jrst iioerr]		; and report it

; Output connected, now wait for input

	sos watskt			; now select receive socket
	mtape net,watcod		; wait for input
	move x,watsta			; get status
	txne x,77			; only error code
	 jrst conerr			; error?
	getsts net,y			; get error bits for message
	txne y,ioimpm\ioderr\iodter\iobktl\iodend\hdead\ctrov\rset\tmo
	 jrst iioerr			; too bad
	txc x,rfcs\rfcr			; for next instruction to win
	txne x,rfcs\rfcr		; RFC sent+received?
	 jrst [	txne x,clss\clsr	; close sent?
		 jrst refuse		; yes, refused
		movx y,tmo		; no, fake a time out
		jrst iioerr]		; and continue

	outstr [asciz/Open
/]

; (continued on next page)
subttl Final pre-display initialization

; Random other pre-execution initialization crufties

	movx x,8.			; 8 bit bytes you know
	dpb x,[300600,,ntibf+1]		; hack input buffer
        dpb x,[300600,,ntobf+1]		; and output buffer
	movx x,inttty\intclk\intinr\intins\intims\intinp\inttti
	clkint 60.*clkspd		; set clock ticking
	intenb x,			; enable interrupt conditions
	mtape net,[15 ? 1]		; maximum allocation

; Send terminal characteristics

	move z,[440600,,cnsblk]		; load sixbit pointer to TTY chars
	movx y,6*cnsbll			; load number of bytes to do
ttchsn:	ildb x,z			; get a character
	call netoc1			; output it
	sojg y,ttchsn			; loop until done
	call netsnd			; now force it out

; Now get server's greeting message

grtmsg:	call netich			; get a character from the network
	caxn x,%tdnop			; hit the no-op yet?
	 jrst grtdun			; yes, greeting message done
	outchr x			; output it
	jrst grtmsg			; and loop for next
subttl Slurp up and send terminal ID

; Tell SUPDUP server to expect terminal name

grtdun:	movx x,300			; escape to SUPSER
	call netoc1			; send it
	movx x,302			; set TTY id
	call netoc1			; send it
	skipn ptyp			; is it a PTY?
	 jrst phstrm			; no, physical terminal
	movsi 377777			; half a moby
	setpr2				; map in the monitor
	 barf [asciz/Can't map monitor!
/]
	move x,ttynum			; get our TTY number
	add x,400270			; pointer into PTYJOB table
	hrrz x,400000-121(x)		; get number of job's controller
	movx y,%lhalf\137		; where string pointer is
	movx z,y			; where to put result
	movx 0,x			; pointer to block
	jobrd				; get address of string in PTY controller
	 jrst ptyluz			; JOBRD failed???  here?
	jumpe y,ptyluz			; if zero string pointer
	txne y,%lhalf			; or with a left half
	 jrst ptyluz			; then not using 137 protocol
	hrli y,-11.			; read 11 words
	movei z,ttystr			; into terminal string
	jobrd				; read
	 jrst ptyluz			; lose again
	move x,ttystr			; get first word of block
	caxe x,'TERMID			; is it SIXBIT/TERMID/?
	 jrst ptyluz			; not using 137 protocol
	move y,[440700,,ttystr+1]	; is, use this string
	jrst sndid1			; and send it along

ptyluz:	move y,[440700,,[asciz/PTY Datamedia/]]
	skipe netp			; is it a network user?
	 move y,[440700,,[asciz/ARPAnet Datamedia/]]
	jrst sndid1			; and send it

; Now try to get the file

phstrm:	open dsk,[0 ? 'DSK,, ? dsibf]	; try to get a DDB
	 barf [asciz/Can't OPEN the DSK!
/]
	movx x,sixbit/ROOMS/		; file name
	setzb y,z			; extension, date cruft
	movx a,sixbit/  PDOC/		; PPN
	lookup dsk,x			; try to find file
	 jrst [	burp [asciz/ROOMS[P,DOC] is gone!
/]
		jrst rndtid]		; lose

; Compute name we must look for

	hrroi y,[17000,,y]		; my responsible TTY
	ttyset y,			; get my TTY #
	jumpe y,fndrom			; found it now if TTY 0
;	jrst search			; and search for it
; Now search for terminal

search:	call getch			; get a character
	 call getch			; got CR, get the LF (we're trusting)
	  jrst search			; no line feed
	sojg y,search			; got line feed, punt if done

; Found the terminal name, now flush TTY name and spaces

	movx y,8.			; skip over TTY name
fndrom:	call getch			; gobble down TTY name
	 jrst [	burp [asciz/ROOMS[P,DOC] in bad format!
/]
		jrst rndtid]		; somebody better fix ROOMS[P,DOC] !!
	sojg y,fndrom
	caxn x,<" >			; space?
	 jrst flsspc			; yes, roomless TTY
sndrom:	call netoc1			; send character out
	call getch			; get a character
	 jrst [	burp [asciz/ROOMS[P,DOC] in bad format!
/]
		jrst rndtid]		; somebody better fix ROOMS[P,DOC] !!
	caxe x,<" >			; saw a space?
	 jrst sndrom			; nope, okay to send it
	call netoc1			; well, can send one space
flsspc:	call getch			; but not any more
	 jrst rndrom			; all done
	caxn x,<" >			; a space to flush?
	 jrst flsspc			; yes, flush it
sndtid:	call netoc1			; not a space, send it
	call getch			; get a character
	 caxa				; all done
	  jrst sndtid			; no, send it out

; Done with sending room, finish that up and get going on real work

sntrom:	movx x,%zeros			; final null
	call netoc1			; send it
tidone:	call netsnd			; force the buffer out
	release dsk,			; free up channel

; (continued on next page)
subttl Initialize screen

	store %zeros,hpos		; to beginning of line
	store %zeros,vpos		; top of screen
	ppact				; flush PP 0
	leypos 2000			; line editor off screen
	skipn dmp			; is it a DM?
	 jrst chkiii			; no, check for III
	store 5*dmbufl,dmcnt		; initialize DM counter
	move [440700,,dmpgm]		; initialize DM pointer
	movem dmpnt			; . . .
	jrst inidpy			; and continue

chkiii:	skipn iiip			; cretinous III?
	 jrst inidpy			; nope
	store %zeros,scp		; all III frobs start with zero
	move iiihdr			; get III header
	movem scp+1			; stuff in III program
inidpy:	call scrini			; init core screen
	store %fword,ovpos		; old vertical position
	lock				; now get locked in core

; Top level sleeper

sleepr:	call scnupd			; update screen if necessary
	iwait				; sleep until next interrupt
	aosg ttiinp			; TTY input?
	 jrst ttiser			; loop around again
	skipn clsedp			; if closing hack network input always
	 aosg ntiinp			; net input?
	  jrst ntiser			; hack it
	jrst sleepr			; else back to sleep
subttl TTY input service

ttiser:	inchrs x			; got a character?
	 jrst [	aosg ntbfop		; was there network output?
		 call netsnd		; force the buffer out
		aosg ntiinp		; net input?
		 jrst ntiser		; yes, hack it
		jrst sleepr]		; nope, back to main loop
	ldb y,[000700,,x]		; get ASCII part of X
	caxn y,↑M			; terpri?
	 inchrw y			; gobble line feed
	andx y,%txctl\%txmta		; get bucky bits of thing
	iori x,(y)			; and bop them on
	store %fword,ntbfop		; flag there is network buffered output
	call netoch			; send it out
	jrst ttiser			; and try for any frobs just came in

; Force the buffer out to the network

netsnd:	ldb x,[410300,,ntobf+1]		; load position field
	movx y,1			; get a bit to hack
	lsh y,(x)			; 2↑# of characters
	subx y,1			; now get null bit flusher mask
	iorm y,@ntobf+1			; make sure the nulls aren't sent
	out net,			; send the character
	 return				; won
	jrst nioerr			; lost

; Auxillary NETOCH

netoc1:	sosg ntobf+2			; space available in buffer?
	 out net,			; no, output the buffer
	  caxa				; win
	   jrst nioerr			; lose
	idpb x,ntobf+1			; put character in buffer
	return				; and return
; Output a character to the network buffer in the hairy way

netoch:	aosn imgchp			; image characters?
	 jrst ntoc2a			; yes, don't map then

;  Map αZ to [CALL], αβZ to α[CALL], α_ to [BACK NEXT], αβ_ to α[BACK NEXT].
; αz and αβz will behave in a similar manner.
;  These mappings are necessary since there is no way that SUPDUP can read a
; [CALL] coming in for the Stanford keyboard, and there is no [BACK NEXT] key
; on them.  For various other obscure characters, commands exist to send them.

	ldb y,[001000,,x]		; get αcharacter
	caxe y,%txctl\"z		; some form of αz?
	 caxn y,%txctl\"Z		; or of αZ?
	  jrst [movx y,↑Z		; yes, convert to [CALL]
		dpb y,[001000,,x]	; save character
		txze x,%txmta		; αβz or αβZ?
		 iorx x,%txctl		; yes, make it α[CALL]
		jrst netoc3]		; now send this bucky command
	caxn y,%txctl\"_		; α_?
	 jrst [	movx y,↑←		; yes, convert to [BACK NEXT]
		dpb y,[001000,,x]	; save character
		txze x,%txmta		; αβ_?
		 iorx x,%txctl		; yes, make it α[BACK NEXT]
		jrst netoc3]		; now go send the frob

;  Map the character from the SAIL to the ITS character set and check for
; if TOPififcation is needed (TECO will treat SAIL graphics as controls
; unless %TXTOP is on).  Then check for any bucky bits.

netoc2:	ldb y,[000700,,x]		; get ASCII part of character
	call outmap			; map to ITS ASCII
	dpb y,[000700,,x]		; and kludge back
	caxl y,↑I			; TAB is not TOPified
	 caxle y,↑M			; neither are LF, VT, FORM, and CR
	  caxn y,<↑[>			;]neither is ALT
	   jrst ntoc2a			; nope, it's a positioning(?) frob
	caxge y,<" >			; all SAIL graphics
	 iorx x,%txtop			; are TOPified (happy TECO)
ntoc2a:	txnn x,%txtop\%txsfl\%txsft\%txmta\%txctl; any bucky bits?
	 jrst [	call netoc1		; nope, just send the frob
		caxn x,"≤		; sending the escape code?
		 call netoc1		; yes, repeat it
		return]			; now return

;  The character has bucky bits, so the intelligent terminal protocol is used to
; send bucky bits: [↑\] [<bucky bits>←-7] [<character>].

netoc3:	move y,x			; swap swap swap
	movx x,↑\			; load escape code
	call netoc1			; put character in buffer
	movx x,"@			; initialize bucky word
	irps bucky,,[%txtop %txsfl %txsft %txmta %txctl]
	 txze y,bucky			; bucky bit?
	  txo x,bucky←-7		; yup
	termin
	call netoc1			; send this cruftie out
	move x,y			; swap back
	call netoc1			; now send the non-bucky character
	return				; and return

; Output mapping from SAIL to ITS character set.

outmap:	skipe dmluzp			; losing DM?
	 jrst allomp			; yah, don't do FCS mappings
	mapit y,137,030			; backarrow
	mapit y,030,137			; underscore

; Common mappings for everything

allomp:	mapit y,033,032			; not equals
	mapit y,032,176			; tilde
	mapit y,175,033			; diamond
	mapit y,176,175			; right curly bracket
	return				; else return
subttl Network input service

; Read a character but don't hang.

ntiser:	sosg ntibf+2			; anything in buffer?
	 jrst [	hrrz x,ntibf		; nope, pointer to next
		hrrz x,(x)		; check next
		skipn clsedp		; closing should slurp always
		 skipge (x)		; anything in next buffer?
		  jrst [in net,		; yes, get a new buffer
			 jrst .+1	; won
			jrst nioerr]	; lost
		mtape net,[10]		; no, any input available?
		 jrst sleepr		; nope, back to sleep
		in net,			; yes, get a new buffer
		 jrst .+1		; won
		jrst nioerr]		; lost
	call nulfls			; flush nulls
	 jrst ntiser			; nulls got flushed
	ldb x,ntibf+1			; get a byte
	caxe x,%tdors			; got an output reset?
	 skipl ntoinp			; still hacking output reset?
	  caxa				; no output flushing
	   jrst ntiser			; sigh

; Check for any display stuff that must be done

	aosn govpos			; get old vertical position?
	 jrst [	store %fword,gohpos	; yes, now get old horizontal position
		jrst ntiser]		; and try for next
	aosn gohpos			; get old horizontal position?
	 jrst [	store %fword,gtvpos	; yes, get vertical position now
		jrst ntiser]		; and try for next
	aosn gtvpos			; get vertical position?
	 jrst [	store %fword,gthpos	; yes, get horizontal position now
		movem x,vpos		; save current vpos now
		store %fword,crupdp	; flag cursor updated
		jrst ntiser]		; and try for next
	aosn gthpos			; get horizontal position?
	 jrst [	movem x,hpos		; set horizontal position
		store %fword,crupdp	; flag cursor updated
		skipn dmp		; is this a DM?
		 jrst ntiser		; no, return
		dmcmd ↑L		; send a cursor position
		move x,hpos		; x position
		xorx x,140		; DM crock
		call dmchar		; output the character
		move x,vpos		; y position
		addx x,2		; give who-line room
		xorx x,140		; DM crock
		call dmchar		; output the character
		jrst ntiser]		; and continue

; (continued on next page)
; Check for other display stuff

	aosn gtiln			; insert lines?
	 jrst inslin			; yup
	aosn gtdln			; delete lines?
	 jrst dellin			; yup
	aosn gtich			; insert characters?
	 jrst inschr			; yup
	aosn gtdch			; delete characters?
	 jrst delchr			; yup
	caxl x,%tdmov			; display code?
	 jrst dpyser			; yes, go do special things

; Check for garbage received and flush it

	jumpe x,[	burp [asciz/Cannot display centered-dot!
/]
			jrst ntiser]	; I thought NULs couldn't happen anymore
	caxn x,↑I			; tab?
	 jrst [	burp [asciz/Cannot display gamma!
/]
		jrst ntiser]		; this shouldn't happen
	caxn x,↑J			; image LF?
	 jrst [	burp [asciz/Cannot display delta!
/]
		jrst ntiser]		; should not happen
	caxn x,↑M			; image CR?
	 jrst [	burp [asciz/Cannot display circle-plus!
/]
		jrst ntiser]		; should not happen

; Good character, so display it

	call inpmap			; map from ITS to SAIL ASCII
	call scstor			; store it on the screen
	jrst ntiser			; continue until this frob empty
; Subroutines for network input service

; Read a character from the network, hanging for it

netich:	sosg ntibf+2			; anything in buffer?
	 in net,			; nope, get some
	  caxa				; won
	   jrst nioerr			; lost
	call nulfls			; call null flusher crock
	 jrst netich			; nulls got flushed
	ldb x,ntibf+1			; get a byte
;	jrst inpmap			; map from ITS to SAIL ASCII

;  Map graphics from ITS extended ASCII to SAIL's extended ASCII.
; First come mappings necessary between SAIL and ITS ASCII

inpmap:	skipe dmluzp			; losing DM?
	 jrst allimp			; yah, too bad
	mapit x,013,136			; uparrow
	mapit x,030,137			; left arrow
	mapit x,032,033			; not equals
	mapit x,033,175			; diamond
	mapit x,136,004			; caret (sigh!!!)
	mapit x,137,030			; underscore
	mapit x,177,013			; integral sign

; Then come mappings which are done going anywhere

allimp:	mapit x,175,176			; right curly brace
	mapit x,176,032			; tilde
	return				; and return

; Flush padding nulls.  Also bumps the byte pointer

nulfls:	ibp ntibf+1			; point to word
	move x,@ntibf+1			; get word of that byte
	andx x,17			; only marking bits
	jffo x,.+2			; count leading zeros
	 jrst cpopj1			; no nulls to flush
	movni x,-44(y)			; get -1,,# of padding characters
	movei y,-1(x)			; # of characters to take off buffer
	subm y,ntibf+2			; remove padding characters from count
	movns ntibf+2			; SUBM goes the wrong way, fix it
	adjbp y,ntibf+1			; move byte pointer
	movem y,ntibf+1			; save pointer
	lsh x,3				; # of bits to shift over
	movni x,(x)			; reverse direction
	move y,@ntibf+1			; get word we are hacking
	lsh y,(x)			; right justify its bytes
	movem y,@ntibf+1		; store it back again
	return				; normal return
subttl Display hacking

dpyser:	caxl x,%tdmax			; a baddie?
	 jrst [	outstr [asciz/Spurious input %TD code (/]
		idivx x,100		; get hundreds
		idivx y,10		; and tens and ones
		repeat 3,[
		 addx x+.rpcnt,"0	; ASCIIify
		 outchr x+.rpcnt	; and print it
		]			; once for each digit
		burp [asciz/) flushed.
/]
		jrst ntiser]		; yes, report it
	xct dpyctb-%tdmov(x)		; no, dispatch on it
	jrst ntiser			; return

;  Dispatch table for ITS cursor control codes.  The server for
; a display code is defined by:
;	DPYSVR code,server instruction
; The servers must be in order by their codes!

define dpysvr code,server
 ifn .-dpyctb-code+%tdmov,.err code is out of order
 server
termin

dpyctb:	dpysvr %tdmov,[store %fword,govpos]
	dpysvr %tdmv1,[store %fword,gtvpos]
	dpysvr %tdeof,[call clreof]
	dpysvr %tdeol,[call clreol]
	dpysvr %tddlf,[call clr1ch]
	dpysvr %tdmtf,[burp [asciz/Spurious input %TDMTF flushed.
/]]
	dpysvr %tdmtn,[burp [asciz/Spurious input %TDMTN flushed.
/]]
	dpysvr %tdcrl,[call terpri]
	dpysvr %tdnop,[jfcl]
	dpysvr %tdbs,[burp [asciz/Spurious input %TDBS flushed.
/]]
	dpysvr %tdlf,[burp [asciz/Spurious input %TDLF flushed.
/]]
	dpysvr %tdrcr,[burp [asciz/Spurious input %TDRCR flushed.
/]]
	dpysvr %tdors,[call oreset]
	dpysvr %tdqot,[burp [asciz/Spurious input %TDQOT flushed.
/]]
	dpysvr %tdfs,[call csraos]
	dpysvr %tdmv0,[store %fword,gtvpos]
	dpysvr %tdclr,[call clrscn]
	dpysvr %tdbel,[call bredle]
	dpysvr %tdini,[burp [asciz/Spurious input %TDINI flushed.
/]]
	dpysvr %tdilp,[store %fword,gtiln]
	dpysvr %tddlp,[store %fword,gtdln]
	dpysvr %tdicp,[store %fword,gtich]
	dpysvr %tddcp,[store %fword,gtdch]
	dpysvr %tdbow,[burp [asciz/Spurious input %TDBOW flushed.
/]]
	dpysvr %tdrst,[burp [asciz/Spurious input %TDRST flushed.
/]]
ifn .-dpyctb-%tdmax+%tdmov,.err %TDMAX is wrong
subttl Display subroutines

; Here to initialize the screen image in core

scrini:	store ascii/     /+1,screen,scrend; write blanks throughout screen
	movx x,<ascii/
/+1>					; DD type of terpri
	movx y,%zeros			; top line
	movx z,1			; blank word
	movx a,nlines			; do for number of lines on screen
scrin1:	movem z,screen(y)		; zap first word on line
	movem z,screen+1(y)		; and second one too
	movem x,screen+nwrdln-2(y)	; put terpri at end
	movem z,screen+nwrdln-1(y)	; and nothingness after that
	addx y,nwrdln			; go to next line
	store %zeros,slupdp-1(a)	; line not updated
	sojg a,scrin1			; loop for next line
glnini:	store 2,scc+2,scc+2+ngw-1	; blank graphics word
	return				; now return

; Here to store a character on the screen

scstor:	move y,vpos			; line position
	store %fword,slupdp(y)		; flag this line changed
	store %fword,scupdp		; and that there is a change
	imulx y,nwrdln			; number words/line
	move z,hpos			; x position
	camle z,tcmxh			; greater than line length
	 jrst [	aos hpos		; account for it anyway
		return]			; and flush the attempt
	idivx z,5			; word position
	addi y,screen+2(z)		; address of word to hack
	dpb x,scbytp(z+1)		; save character on screen
	aos hpos			; bump X position
	skipe dmp			; is this a DM?
	 jrst dmchar			; yes, output this character
	return				; and return

; Here to clear the screen

clrscn:	store %zeros,vpos		; top line
	store %zeros,hpos		; leftmost column
	call scrini			; initialize screen
	store %fword,saupdp		; updated entire screen
	call scnupd			; now update the screen
	skipn dmp			; is this a DM?
	 return				; no, return
	dmcmd ↑L			; set cursor position
	movx x,140			; beginning of line
	call dmchar			; output the character
	movx x,142			; line 2
	call dmchar			; output it
	move y,tcmxv			; get height of screen
dmceof:	dmcmd ↑W			; clear this line
	dmcmd ↑M			; and go to next line
	sojg y,dmceof			; and continue clearing
	dmcmd ↑L			; set cursor position
	movx x,140			; beginning of line
	call dmchar			; output the character
	movx x,142			; line 2
	call dmchar			; output it
	jrst dmout			; force it all out
; Non-insert/delete display subroutines

; Here to clear to EOL

clreol:	skipe dmp			; is this a DM?
	 jrst [	dmcmd ↑W		; yes, send line zapper
		jrst .+1]		; and return
	move b,hpos			; get the position now
	caxl b,linel			; if done
	 return				; flush
	move y,vpos			; get vertical position
	store %fword,slupdp(y)		; flag this line changed
	store %fword,scupdp		; and that there is a change
	imulx y,nwrdln			; number of words/line
	move z,hpos			; save horizontal position
	idivx z,5			; word position
	addi y,screen+2(z)		; address of word to hack
	move z,scbytp(z+1)		; get byte pointer
	movx x,<" >			; space in the character
	dpb x,z				; zap this character
cleol1:	addx b,1			; bump character pointer
	caxl b,linel			; got to EOL yet?
	 return				; and return
	idpb x,z			; zap another character
	jrst cleol1			; nope, not done yet

; Here to delete a character forward

clr1ch:	skipe dmp			; is this a DM?
	 jrst [	dmcmd <" >		; yes, zap out the character
		dmcmd ↑H		; back up
		jrst .+1]		; and continue
	movx x,<" >			; a blank space
	move y,vpos			; line position
	store %fword,slupdp(y)		; flag this line changed
	store %fword,scupdp		; and that a change happened
	imulx y,nwrdln			; number of words/line
	move z,hpos			; horizonal position
	idivx z,5			; word position
	addi y,screen+2(z)		; address to be hacked
	dpb x,scbytp(z+1)		; shove character in
	return				; and return

; Here to terpri

terpri:	skipe dmp			; is this a DM?
	 jrst [	dmcmd ↑M		; yes, do a CR
		jrst .+1]		; and continue
	store %zeros,hpos		; to beginning of line
	aos y,vpos			; bump vertical position
	caml y,tcmxv			; gone too far?
	 jrst [	move y,[screen+nwrdln,,screen]; foo!  gotta scroll (sigh)
		blt y,screen+scrsiz-nwrdln-1; the big BLT strikes again
		store ascii/     /+1,botlin+1,botlin+<nchars/5>
		store %fword,saupdp	; I can't believe I updated the WHOLE thing
		move tcmxv ? sos ? movem vpos; set vertical position to bottom line
		jrst .+1]		; and continue
	store %fword,crupdp		; flag cursor has moved
	jrst clreol			; and now clear the line
; More display subroutines

; Here to breedle

bredle:	movx x,%fword			; → own speaker
	beep x,				; breedle...
	return				; and return

; Here to respond to an output reset

oreset:	movx x,↑\			; escape code
	call netoc1			; send it
	movx x,↑P			; ready to send cursor position
	call netoc1			; here it comes...
	move x,vpos			; vertical position
	call netoc1			; . . .
	move x,hpos			; horizontal position
	call netoc1			; . . .
	aos ntoinp			; flush one net interrupt
	jrst netsnd			; force these crufies out

; Here to forespace

csraos:	skipe dmp			; is this a DM?
	 jrst [	dmcmd ↑\		; yes, space forward
		jrst .+1]		; and continue
	aos hpos			; bump horizontal position
	store %fword,crupdp		; flag cursor updated
	return				; and return

; Here to clear to EOF

clreof:	save hpos			; save current horizontal pos
	save vpos			; ditto for vertical
cleof1:	call clreol			; clear to end of line
	dmcmd ↑M			; next line
	store %zeros,hpos		; now clear all of the lines below
	aos x,vpos			; bump to new line
	caxge x,nlines			; all done yet?
	 jrst cleof1			; nope, kill next line
	retr vpos			; get back old vertical position
	retr hpos			; and horizontal position
	dmcmd ↑L			; set cursor position
	move x,hpos			; horizontal position
	xorx x,140			; DM crock
	call dmchar			; output it
	move x,vpos			; vertical position
	xorx x,140			; DM crock
	call dmchar			; output it
	return				; and return
; Line insert

inslin:	skipn dmp			; is this a DM?
	 jrst insl0a			; nope
	dmcmd ↑P			; yes, enter i/d mode
insl0a:	move a,x			; copy # of lines to hack
insln0:	skipn dmp			; DM again?
	 jrst insl1a			; nope
	dmcmd ↑J			; insert a line
insl1a:	move x,vpos			; load vertical position
	imulx x,nwrdln			; make into word counter
	addi x,screen			; address of first word of cursor line
	cain x,screen+<nlines-1>*nwrdln	; skip unless at bottom line
	 jrst insln2			; on bottom, zap it
	move y,[screen+<nlines-2>*nwrdln,,screen+<nlines-1>*nwrdln]
insln1:	move z,y			; copy pointer
	blt z,nwrdln-1(y)		; copy one line
	adjsp y,-nwrdln			; offset a line
	caie x,(y)			; done yet?
	 jrst insln1			; nope
insln2:	store ascii/     /+1,2(x)	; blanks
	movei y,nwrdln-2-1(x)		; number to do
	addx x,3			; address offset
	hrli x,-1(x)			; complete pointer
	blt x,(y)			; zak!
	sojg a,insln0			; loop for more lines
	store %fword,saupdp		; updated the world
	skipn dmp			; on a DM?
	 jrst ntiser			; no, just return
	dmcmd ↑X			; yes, leave i/d mode
	jrst ntiser			; and return
; Line delete

dellin:	skipn dmp			; is this a DM?
	 jrst dell0a			; nope
	dmcmd ↑P			; yes, enter i/d mode
dell0a:	move a,x			; copy # of lines to hack
delln0:	skipn dmp			; is this a DM?
	 jrst dell1a			; nope
	dmcmd ↑Z			; delete a line
dell1a:	move x,vpos			; get vertical position
	imulx x,nwrdln			; frobs to do
	addi x,screen			; address of first word of cursor line
	cain x,screen+<nlines-1>*nwrdln	; at bottom line?
	 jrst delln1			; yup, just copy extra line in
	movei y,(x)			; make a copy
	addx y,nwrdln			; address of next line
	hrli x,(y)			; make a BLT pointer
	blt x,screen+<nlines-1>*nwrdln-1; copy the lines
delln1:	store ascii/     /+1,2(x)	; blanks
	movei y,nwrdln-2-1(x)		; number to do
	addx x,3			; address offset
	hrli x,-1(x)			; complete pointer
	blt x,(y)			; zak!
	sojg a,delln0			; loop for more lines
	store %fword,saupdp		; updated the world
	skipn dmp			; on a DM?
	 jrst ntiser			; no, just return
	dmcmd ↑X			; leave i/d mode
	jrst ntiser			; and return
; Character insert

inschr:	skipn dmp			; is this a DM?
	 jrst insc0a			; nope
	dmcmd ↑P			; yes, enter i/d mode
insc0a:	move c,x			; copy character counter
insch0: skipn dmp			; on a DM?
	 jrst insc1a			; nope
	dmcmd ↑\			; insert a character
insc1a:	move x,vpos			; get vertical position
	imulx x,nwrdln			; now number of words
	move a,x			; copy it for hacking
	addi a,screen+nwrdln-3		; address of last text word
	move y,hpos			; get horizontal position
	idivx y,5			; make it words
	addi x,screen+2(y)		; address of word with cursor
	ldb y,[010700,,(x)]		; first character in next word
	ldb b,[	103400,,(x)
		102500,,(x)
		101600,,(x)
		100700,,(x)
		100000,,(x)](z)		; bytes after character
	dpb b,[	013400,,(x)
		012500,,(x)
		011600,,(x)
		010700,,(x)
		010000,,(x)](z)		; get shifted over one
	movx b,<" >			; space in hole
	dpb b,[	350700,,(x)
		260700,,(x)
		170700,,(x)
		100700,,(x)
		010700,,(x)](z)
	jrst insch1			; check for being done

; At each iteration Y has last character, X has next address

insch2:	move z,y			; copy the character
	ldb y,[010700,,(x)]		; first character in next word
	dpb z,[000700,,(x)]		; last character here
	move z,(x)			; get word being hacked
	rot z,-7			; put characters in right place
	iorx z,1			; make sure bit 1.1 is on
	movem z,(x)			; save character in word
insch1:	came x,a			; at last address?
	 aoja x,insch2			; nope
	store %fword,scupdp		; some update somewhere
	move x,vpos			; this line
	sojg c,insch0			; loop for more characters
	store %fword,slupdp(x)		; this line was hacked
	skipn dmp			; on a DM?
	 jrst ntiser			; no, just return
	dmcmd ↑X			; leave i/d mode
	jrst ntiser			; and return
; Character delete

delchr:	skipn dmp			; is this a DM?
	 jrst delc0a			; nope
	dmcmd ↑P			; yes, enter i/d mode
delc0a:	move c,x			; copy number of characters to hack
delch0:	skipn dmp			; on a DM?
	 jrst delc1a			; nope
	dmcmd ↑H			; delete a character
delc1a:	move x,vpos			; get current vertical position
	imulx x,nwrdln			; number of words
	move a,x			; save it for later
	addi a,screen+nwrdln-3		; address of last text word in line
	move y,hpos			; get horizontal position
	idivx y,5			; number of words
	addi x,screen+2(y)		; address of word with cursor
	ldb b,[	013400,,(x)
		012500,,(x)
		011600,,(x)
		010700,,(x)
		010000,,(x)](z)
	dpb b,[	103400,,(x)
		102500,,(x)
		101600,,(x)
		100700,,(x)
		100000,,(x)](z)
	jrst delch1			; check for being done

; Each time around the iteration A had address of next word

delch2:	ldb y,[350700,,(x)]		; last character in previous
	dpb y,[010700,,-1(x)]		; to previous
	ldb y,[013400,,(x)]		; get last characters in this word
	dpb y,[103400,,(x)]		; put back left justified
delch1:	came x,a			; done?
	 aoja x,delch2			; not yet
	movx y,<" >			; get a space
	dpb y,[010700,,(x)]		; blank out last column
	store %fword,scupdp		; screen updated someplace
	move x,vpos			; get this line
	sojg c,delch0			; hack another character
	store %fword,slupdp(x)		; flag this line hacked
	skipn dmp			; on a DM?
	 jrst ntiser			; no, just return
	dmcmd ↑X			; leave i/d mode
	jrst ntiser			; and return
subttl Display update subroutines

scnupd:	skipe slowip			; in slow mode?
	 jrst scnup1			; yes, good enough
	movx x,<-nlines,,>		; load pointer to line update table
	movx y,%zeros			; initialize line count
	skipe slupdp(x)			; does this line need hacking?
	 addx y,1			; yup, bump count
	aobjn x,.-2			; try for more lines
	skipn iiip			; III always updates everything
	 caxl y,nlnupd			; three lines or so?
	  store %fword,saupdp		; yup, must update screen
scnup1:	aose saupdp			; update entire screen?
	 jrst scupd1			; nope, maybe selective
	store %zeros,scupdp		; clear other update flags
	store %zeros,slupdp,slupdp+nlines-1; . . .
	skipe dmp			; is this a DM?
	 jrst csrupd			; and update the cursor
	upgiot sdisp			; output new screen
;	jrst csrupd			; now update cursor

; Update cursor

csrupd:	skipe dmp			; is this a DM?
	 jrst [	dmcmd ↑L		; yes, send a cursor pos
		move x,hpos		; horizontal position
		xorx x,140		; DM crock
		call dmchar		; output it
		move x,vpos		; vertical position
		addx x,2		; room for who line
		xorx x,140		; DM crock
		call dmchar		; output it
		jrst dmout]		; force it out and return
	skipn ddp			; is this a DD?
	 return				; nope, too bad III
	skipe cdisp+2			; finished with the last display?
	 upgiot [0 ? 0 ? 0 ? 0]		; no, sit and wait
	call glnini			; clear cursor line
	skipge x,ovpos			; got an old position?
	 jrst .+3			; nope, don't try to clear old
	  call getcsy			; get cursor vertical position
	  ddupg cclear			; clear cursor
	move x,hpos			; horizontal character position
	imulx x,6			; horizontal bit position
	addx x,2			; graphics mode hack
	idivx x,32.
	movns y
	movx z,(740000)
	lsh z,(y)
	ldb a,[010300,,z]
	rot a,-3
	andx z,777777777760
	iorx z,2
	iorx a,2
	movem z,scc+2(x)
	movem a,scc+3(x)
	move x,vpos			; get current vertical position
	movem x,ovpos			; save as old position
	call getcsy			; get cursor vertical position
	ddupg cdisp			; and send it all out
	return				; finally return

scupd1:	aose scupdp			; did any update happen?
	 jrst scupd2			; nope, try for just cursor
	movx x,<-nlines,,>		; load line pointer
scup1a:	skipe slupdp(x)			; need to hack this line?
	 call updlin			; yup
	aobjn x,scup1a			; loop for next line
	jrst csrupd			; now update cursor

scupd2:	aose crupdp			; was cursor hacked
	 return				; nope, just return
	jrst csrupd			; yes, then hack the cursor
; More display updating stuff

; Set up display program vertical position

getcsy:	imulx x,12.
	addx x,24.+10.
	dpb x,[140400,,scc+1]
	lsh x,-4
	dpb x,[240500,,scc+1]
	return				; and return

; Display a single line

updlin:	skipe dmp			; don't do this garbage if a DM
	 return				; flitter back immediately
	skipe ldisp+2			; finished with the last display?
	 upgiot [0 ? 0 ? 0 ? 0]		; no, sit and wait
	store %zeros,slupdp(x)		; am updating now
	hrrz y,x			; line number
	imulx y,nwrdln			; word position
	movsi y,screen+2(y)		; address of start of line
	hrri y,linprg+2			; and where line is going to
	blt y,linprg+nwrdln-2		; copy line
	hrrz z,x			; get line number again
	imulx z,12.
	addx z,24.			; starting raster number
	dpb z,[140400,,linprg]		; zap in low 4 bits of address
	lsh z,-4			; throw low bits away
	dpb z,[240500,,linprg]		; high 5 bits of address
	upgiot ldisp			; display the line
	return				; now return
subttl DM display routines

; Character output to DM

dmchar:	sosg dmcnt			; any room in buffer?
	 call dmout			; nope, output the buffer
	idpb x,dmpnt			; save character
	return				; and return

; Redraw DM screen, aborts any undone DM output

dmredw:	store %zeros,dmpgm,dmpgm+dmbufl-1; clear the old program
	store <5*dmbufl>-4,dmcnt	; initialize DM counter
	move [440700,,dmpgm]		; initialize DM pointer
	movem dmpnt			; . . .
	save hpos ? save vpos		; save current cursor position
	dmcmd ↑L			; set cursor position
	movx x,140			; beginning of line
	call dmchar			; output the character
	movx x,142			; line 2
	call dmchar			; output it
	move y,tcmxv			; get height of screen
dmred1:	dmcmd ↑W			; clear this line
	dmcmd ↑M			; and go to next line
	sojg y,dmred1			; and continue clearing
	dmcmd ↑L			; set cursor postion
	movx x,140			; beginning of line
	call dmchar			; set X position
	movx x,142			; second line from top
	call dmchar			; output that too
	store %zeros,vpos		; starting at top
	movn z,tcmxv			; get number of lines
	hrlzs z				; make it an AOBJN pointer
dmdrw1:	movx y,nwrdln			; number of words to offset
	imuli y,(z)			; compute offset from start of screen
	add y,[440700,,screen+1]	; absolute address of line's characters-1
	store %zeros,hpos		; start at beginning of line
dmdrw2:	ildb x,y			; get a character from the line
	jumpe x,dmdrw2			; flush nulls
	call dmchar			; output the character
	aos x,hpos			; bump horizontal position
	came x,tcmxh			; gotten to end of the line?
	 jrst dmdrw2			; yes
	store %zeros,hpos		; end of this line
	aos vpos			; bump vertical position
	dmcmd ↑M			; new line
	aobjn z,dmdrw1			; and loop for next line
	retr vpos ? retr hpos		; get back old cursor position
;	jrst dmout			; and output the mess

; Buffer output to DM; called when DM buffer full or want to force buffer out

dmout:	skipn dmpgm			; any program there?
	 return				; lets not get overenthusiastic
	hrrz dmpnt			; get current value of pointer
	subi dmpgm-1			; compute number of words used
	movem dmdisp+1			; set number of words to do
	upgiot dmdisp			; output DM program
	movs hpos			; get current X position
	hrr vpos			; and Y position
	addx 0,2			; give the who line some space
	cursor				; bop the cursor to last position
	store %zeros,dmpgm,dmpgm+dmbufl-1; clear the old program
	store <5*dmbufl>-4,dmcnt	; initialize DM counter
	move [440700,,dmpgm]		; initialize DM pointer
	movem dmpnt			; . . .
	movx 0,177			; quote
	idpb dmpnt			; put in buffer
	movx 0,↑L			; cursor position
	idpb dmpnt			; bufferify
	move hpos			; horizontal position
	xorx 0,140			; DM crock
	idpb dmpnt			; bop away
	move vpos			; vertical position
	addx 0,2			; who line space
	xorx 0,140			; DM crock
	idpb dmpnt			; bop away
	return				; and return
subttl SUPDUP commands

cmdcmd:	inchrw x			; get command character
	ldb y,[001000,,x]		; get αcharacter
	caxl y,"a			; lowercase?
	 caxle y,"z			; . . .
	  caxa				; no
	   txz x,<" >			; yes, uppercasify
	caxe x,"K			; logout foreign job?
	 caxn x,"L			; . . .
	  jrst [movx x,300		; escape code
		call netoc1		; prepare for escape
		movx x,301		; kill other job code
		call netoc1		; send it too
		call netsnd		; now send this command out
		outstr [asciz/Logged out foreign job./]
		jrst @quit]		; and die
	caxn x,"Q			; quit?
quit:	 jrst [	hrroi y,[004000,,400\"N]; yes, [BREAK]N
		ttyset y,		; clear the screen
		exit]			; and exit out

; (continued on next page)
; Display only commands

	caxn x,"H			; [HELP]?
	 jrst [	txo x,%txtop		; TOPify
		jrst imgsnd]		; and send it out
	caxn x,"F			; fast mode?
	 jrst [	store %zeros,slowip	; yes
		outstr [asciz/Fast display mode!
/]
		return]			; and continue hacking
	caxe x,"?			; help?
	 caxn x,"P			; page printer restore?
	  jrst [caxn x,"?		; was it a help?
		 jsp z,[hrroi y,[004000,,"C]; [ESCAPE]C
			ttyset y,	; clear the screen
			ppsel 400002	; yes, select PP 2 but don't activate yet
			outstr hlptxt	; display help text
			ppact 100000	; now activate PP 2
			jrst 3(z)]	; and continue
		ppact 400000		; activate PP 0
		hrroi y,[004000,,400\"P]; [BREAK]P
		ttyset y,		; refresh screen
		outstr [asciz/Type any character to return to ITS:/]
		inchrw y		; get a character
		outstr [asciz/
/]
		clrbfi			; flush any other input (like CRLF)
		caxn x,"?		; was it a help frob?
		 pprel 2		; flush temporary page printer
		jrst @review]		; and review screen
	caxn x,"R			; screen record crock?
	 jrst record			; yes, write record file
	caxn x,"S			; slow mode?
	 jrst [	store %fword,slowip	; yes
		outstr [asciz/Slow display mode!
/]
		return] 		; and continue gobbling input
	caxn x,"V			; re-view screen?
review:	 jrst [	leypos 2000		; line editor off screen
		ppact			; flush all PP's
		skipe dmp		; is this a DM?
		 call dmredw		; redraw the whole screen
		store %fword,saupdp	; must redisplay whole screen
		call scnupd		; update screen
		store %zeros,ntoinp	; clear output resets
		return]			; all done

; (continued on next page)
; Esoteric character mappings (all magical)

	caxe y,%txctl\"z		; αz or αβz?
	 caxn y,%txctl\"Z		; αZ or αβZ?
	  jrst imgsnd			; yes, send it in image form
	caxn y,%txctl\"_		; α_ or αβ_?
	 jrst [	addx x,"←-"_		; map it first
		jrst imgsnd]		; and send it
	txz y,%txctl			; flush αification
	caxn y,".			; centered-dot?
	 jrst [	addx x,%txtop-".	; yes
		jrst imgsnd]		; and send it
	caxe y,↑I			; gamma?
	 caxn y,↑J			; delta?
	  jrst [addx x,%txtop		; yes
		jrst imgsnd]		; and send it
	caxe y,↑M			; circle-plus?
	 caxn y,177			; integral?
	  jrst [addx x,%txtop		; yes
		jrst imgsnd]		; and send it
	caxn y,"∂			; [NULL]?
	 jrst [	subx x,"∂		; yes
		jrst imgsnd]		; and send it
	caxe y,"λ			; λ?  [BACK SPACE]
	 caxn y,"∨			; ∨?  [BACK NEXT]
	  jrst imgsnd			; yes, send it
	caxn y,"≠			; ≠?  [CALL]
	 jrst [	subx x,"≠-"~		; yes, convertify (cretin character set)
		jrst imgsnd]		; yes, send it
	caxn y,"α			; α?  [ESCAPE]
	 jrst [	addx x,%txtop\<"A-"α>	; yes, change α to [ESCAPE]
		jrst imgsnd]		; and send it
	caxn y,"β			; β?  [BREAK]
	 jrst [	addx x,%txtop\<"B-"β>	; yes, change β to [BREAK]
		jrst imgsnd]		; and send it
	caxn y,"ε			; ε?  [CLEAR]
	 jrst [	addx x,%txtop\<"C-"ε>	; yes, change ε to [CLEAR]
		jrst imgsnd]		; and send it
	caxn y,"↑			; ↑?  uparrow
	 jrst [	addx x,%txtop+013-"↑	; yes, change ↑ to uparrow
		jrst imgsnd]		; and send it

; (continued on next page)
; Magic DDT command, subroutines, etc.

	caxn x,"D			; enter DDT | RAID?
	 jrst ddtcal			; call DDT

; If not a command or a magical character, burp

	outchr ["']			; quote it
	outchr x			; output the loser
	burp [asciz/' is an illegal command character.
/]
	movx x,%fword			; to myself
	beep x,				; breedle!
	return

imgsnd:	store %fword,imgchp		; image characters now
	call netoch			; send it too
	jrst netsnd			; send it out
; SUPDUP help text

hlptxt:	asciz/Commands:

F	New fast display mode		H	Send [HELP] ("help" key)
K or L	Kill job and quit		P	View page printer
Q	Detach job and quit		R	Write a screen record
S	Old slow display mode		V	Re-draw screen
?	Type this message

Special mappings:

 .	centered-dot	[TAB]	gamma		[LF]	delta
 [CR]	circle-plus	[BS]	integral	⊗	[NULL]
 λ	[BACK SPACE]	≠	[CALL]		∨	[BACK NEXT]
 α	[ESCAPE]	β	[BREAK]		ε	[CLEAR]

↑, α↑, β↑, αβ↑, αz, αβz, αZ, αβZ, α_, and αβ_ are not mapped in command mode.
/
subttl Screen record crock

tmploc jobren,reentr

reentr:	setzm jobren			; flag to exit
record:	open dsk,[0 ? 'DSK,, ? dsobf,,]	; get a disk channel
	 barf [asciz/Unable to OPEN the DSK!
/]
	skipn jobren			; if reentering
	 jrst recrd0			; don't hack things much
	hrroi x,[004000,,400\"N]	; [BREAK]N
	ttyset x,			; normalize screen
	ptjobx [0 ? sixbit/DON/]	; turn echoing on
	movx x,%fword			; this terminal
	getlin x			; get line characteristics
	txz x,spcbrk			; special activation mode bit
	setlin x			; leave SAM
	setact [[777777,,777777		; activate on 000 - 043
		 777700,,037600		;  044 - 107
		 000000,,374000		;  110 - 153
		 000007,,600000]]	;  154 - 177
recrd0:	outstr [asciz/Writing screen record.../]
	movx x,<-nlines,,>		; number of lines to write
recrd1:	movx y,nwrdln			; number of words to offset
	imuli y,(x)			; compute offset from start of screen
	add y,[440700,,screen+1]	; absolute address of line's characters-1
recrd2:	ildb z,y			; get a character from the line
	jumpe z,recrd2			; bop away nulls
	sosg dsobf+2			; any room in the buffer?
	 out dsk,			; no, dump out what's there now
	  caxa				; won
	   barf [asciz/Disk OUT failed!
/]
	idpb z,dsobf+1			; save character
	caxe z,↑J			; hit the line feed yet?
	 jrst recrd2			; not yet
	aobjn x,recrd1			; won
	close dsk,			; close off file
	release dsk,			; free up channel
	skipn jobren			; if reentered
	 exit				; just exit
	ptjobx [0 ? sixbit/DOFF/]	; turn echoing off
	movx x,%fword			; this line
	getlin x			; get line characteristics
	txo x,spcbrk			; special activation mode bit
	setlin x			; enter SAM
	setact [[777777,,777777		; activate on 000 - 043
		 777777,,777777		;  044 - 107
		 777777,,777777		;  110 - 153
		 777777,,600000\allact\bsact\supscm\supccr]]; 154 - 177, αβ act
	ppact				; flush PP 0
	jrst @review			; and redraw screen
subttl Network error analysis

; Connection refused

refuse:	outstr [asciz/Refused./]
	exit

; Connection closed by foreign host

closed:	outstr [asciz/Host closed connection./]
	exit

; Failed to get socket number from logger

nosock:	getsts icp,y			; get channel status of loser
	jrst iioerr			; and report why it happened

; CONNECT MTAPE error codes

define cnemes code,message/
 ifn 1+.-cnetab-code,.err code is out of order
 [asciz/message/]
termin

cnetab:	cnemes siu,Socket already in use.
	cnemes ccs,Can't change socket numbers.
	cnemes sys,Horrible system error.
	cnemes nla,No links available.
	cnemes ilb,Illegal byte size.
	cnemes idd,Local NCP dead.
	cnemes gmm,Homosocketual connection.
cnemax==1+.-cnetab

; CONNECT MTAPE failed

conerr: andx x,77			; only error code
	caxl x,cnemax			; error code too high?
	 jrst [	outstr [asciz/Connection failed, code #/]
		idivx x,10		; split into two digits
		repeat 2,[
		 addx x+.rpcnt,"0	; ASCIIify
		 outchr x+.rpcnt	; output the digit
		]			; once for each digit
		outchr [".]		; final dot
		exit]			; and die
	outstr @cnetab-1(x)		; output error message
	exit				; and exit
; More network error reporting

; IMP I/O error

nioerr:	getsts net,y			; get error status
	skipe clsedp			; known that it was closing?
	 jrst closed			; okay, report that instead
iioerr:	andx y,ioimpm\ioderr\iodter\iobktl\iodend\hdead\ctrov\rset\tmo
	txzn y,hdead
	 jrst cctrov
	txz y,ioderr\iodter		; clear other error bits
	outstr [asciz/Host dead./]
	jumpe y,[exit]			; punt if done
	outstr [asciz/
/]
cctrov:	txnn y,ctrov
	 jrst crset
	txz y,ioderr\iodter		; clear other error bits
	outstr [asciz/Host exceeded allocation./]
	jumpe y,[exit]			; punt if done
	outstr [asciz/
/]
crset:	txnn y,rset
	 jrst ctmo
	txz y,ioderr\iodter		; clear other error bits
	outstr [asciz/Host reset./]
	jumpe y,[exit]			; punt if done
	outstr [asciz/
/]
ctmo:	txnn y,tmo
	 jrst ceof
	txz y,ioderr\iodter		; clear other error bits
	outstr [asciz/Time out./]
	jumpe y,[exit]			; punt if done
	outstr [asciz/
/]
ceof:	txnn y,iodend
	 jrst cbktl
	txz y,ioderr\iodter		; clear other error bits
	outstr [asciz/Host closed connection./]
	jumpe y,[exit]			; punt if done
	outstr [asciz/
/]
cbktl:	txne y,iobktl\ioimpm		; argh!!!
	 barf [asciz/IOIMPM or IOBKTL!
Find a wizard./]

; Occasionally IODTER and IODERR get set with nothing else.

	txze y,iodter			; for this bit or the other
	 txo y,ioderr			; or both
	caxn y,ioderr			; for when only this bit is set
	 outstr [asciz/Incomplete transmission./]
	exit				; and die
subttl Random routines, literals, etc.

; Here if could not get terminal name; give a random string

rndtid:	burp [asciz/Unable to get terminal's location from ROOMS[P,DOC].
/]
	move y,[440700,,[asciz/Unknown Data Disc/]]
	skipe iiip			; is it a III?
	 move y,[440700,,[asciz/Unknown III/]]
	skipn dmp			; is it a DM?
	 jrst sndid1			; no
	skipa y,[440700,,[asciz/Unknown Datamedia/]]
rndrom:	 move y,[440700,,[asciz/Unassigned Room/]]
sndid1:	ildb x,y			; get a character
	call netoc1			; send it
	jumpn x,sndid1			; and continue if not done
	jrst tidone			; all done

; Here to get a character from terminal rooms table

getch:	sosg dsibf+2			; buffer ready?
	 in dsk,			; no, get one then
	  caxa				; won
	   jrst rndtid			; lost, send random name
	ildb x,dsibf+1			; get a character
	jumpe x,getch+1			; flush nulls
	caxe x,↑M			; hit a terpri?
cpopj1:	 aos (p)			; no, bump return PC
	return				; now return

; Literals

...lit:	variables			; don't like variables!
if1,ifn .-...lit,.err Variables lose lose lose

	constants			; generate constants

sdpff=.					; first free location in SUPDUP

end SUPDUP